/src/gdal/ogr/ogrsf_frmts/gmlas/ogrgmlaslayer.cpp
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /******************************************************************************  | 
2  |  |  * Project:  OGR  | 
3  |  |  * Purpose:  OGRGMLASDriver implementation  | 
4  |  |  * Author:   Even Rouault, <even dot rouault at spatialys dot com>  | 
5  |  |  *  | 
6  |  |  * Initial development funded by the European Earth observation programme  | 
7  |  |  * Copernicus  | 
8  |  |  *  | 
9  |  |  ******************************************************************************  | 
10  |  |  * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>  | 
11  |  |  *  | 
12  |  |  * SPDX-License-Identifier: MIT  | 
13  |  |  ****************************************************************************/  | 
14  |  |  | 
15  |  | #include "ogr_gmlas.h"  | 
16  |  | #include "ogr_pgdump.h"  | 
17  |  | #include "cpl_minixml.h"  | 
18  |  |  | 
19  |  | /************************************************************************/  | 
20  |  | /*                            OGRGMLASLayer()                           */  | 
21  |  | /************************************************************************/  | 
22  |  |  | 
23  |  | OGRGMLASLayer::OGRGMLASLayer(OGRGMLASDataSource *poDS,  | 
24  |  |                              const GMLASFeatureClass &oFC,  | 
25  |  |                              OGRGMLASLayer *poParentLayer,  | 
26  |  |                              bool bAlwaysGenerateOGRPKId)  | 
27  | 7.45k  |     : m_poDS(poDS), m_oFC(oFC),  | 
28  | 7.45k  |       m_poFeatureDefn(new OGRFeatureDefn(oFC.GetName())),  | 
29  | 7.45k  |       m_poParentLayer(poParentLayer)  | 
30  | 7.45k  | { | 
31  | 7.45k  |     m_poFeatureDefn->SetGeomType(wkbNone);  | 
32  | 7.45k  |     m_poFeatureDefn->Reference();  | 
33  |  |  | 
34  | 7.45k  |     SetDescription(m_poFeatureDefn->GetName());  | 
35  |  |  | 
36  |  |     // Are we a regular table ?  | 
37  | 7.45k  |     if (m_oFC.GetParentXPath().empty())  | 
38  | 4.87k  |     { | 
39  | 4.87k  |         if (bAlwaysGenerateOGRPKId)  | 
40  | 0  |         { | 
41  | 0  |             OGRFieldDefn oFieldDefn(szOGR_PKID, OFTString);  | 
42  | 0  |             oFieldDefn.SetNullable(false);  | 
43  | 0  |             m_nIDFieldIdx = m_poFeatureDefn->GetFieldCount();  | 
44  | 0  |             m_bIDFieldIsGenerated = true;  | 
45  | 0  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
46  | 0  |         }  | 
47  |  |  | 
48  |  |         // Determine if we have an xs:ID attribute/elt, and if it is compulsory,  | 
49  |  |         // If so, place it as first field (not strictly required, but more  | 
50  |  |         // readable) or second field (if we also add a ogr_pkid) Furthermore  | 
51  |  |         // restrict that to attributes, because otherwise it is impractical in  | 
52  |  |         // the reader when joining related features.  | 
53  | 4.87k  |         const std::vector<GMLASField> &oFields = m_oFC.GetFields();  | 
54  | 88.0k  |         for (int i = 0; i < static_cast<int>(oFields.size()); i++)  | 
55  | 83.2k  |         { | 
56  | 83.2k  |             if (oFields[i].GetType() == GMLAS_FT_ID &&  | 
57  | 83.2k  |                 oFields[i].IsNotNullable() &&  | 
58  | 83.2k  |                 oFields[i].GetXPath().find('@') != std::string::npos) | 
59  | 7  |             { | 
60  | 7  |                 OGRFieldDefn oFieldDefn(oFields[i].GetName(), OFTString);  | 
61  | 7  |                 oFieldDefn.SetNullable(false);  | 
62  | 7  |                 const int nOGRIdx = m_poFeatureDefn->GetFieldCount();  | 
63  | 7  |                 if (m_nIDFieldIdx < 0)  | 
64  | 7  |                     m_nIDFieldIdx = nOGRIdx;  | 
65  | 7  |                 m_oMapFieldXPathToOGRFieldIdx[oFields[i].GetXPath()] = nOGRIdx;  | 
66  | 7  |                 m_oMapOGRFieldIdxtoFCFieldIdx[nOGRIdx] = i;  | 
67  | 7  |                 m_oMapFieldXPathToFCFieldIdx[oFields[i].GetXPath()] = i;  | 
68  | 7  |                 m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
69  | 7  |                 break;  | 
70  | 7  |             }  | 
71  | 83.2k  |         }  | 
72  |  |  | 
73  |  |         // If we don't have an explicit ID, then we need  | 
74  |  |         // to generate one, so that potentially related classes can reference it  | 
75  |  |         // (We could perhaps try to be clever to determine if we really need it)  | 
76  | 4.87k  |         if (m_nIDFieldIdx < 0)  | 
77  | 4.86k  |         { | 
78  | 4.86k  |             OGRFieldDefn oFieldDefn(szOGR_PKID, OFTString);  | 
79  | 4.86k  |             oFieldDefn.SetNullable(false);  | 
80  | 4.86k  |             m_nIDFieldIdx = m_poFeatureDefn->GetFieldCount();  | 
81  | 4.86k  |             m_bIDFieldIsGenerated = true;  | 
82  | 4.86k  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
83  | 4.86k  |         }  | 
84  | 4.87k  |     }  | 
85  |  |  | 
86  | 7.45k  |     OGRLayer *poLayersMetadataLayer = m_poDS->GetLayersMetadataLayer();  | 
87  | 7.45k  |     OGRFeature *poLayerDescFeature =  | 
88  | 7.45k  |         new OGRFeature(poLayersMetadataLayer->GetLayerDefn());  | 
89  | 7.45k  |     poLayerDescFeature->SetField(szLAYER_NAME, OGRGMLASLayer::GetName());  | 
90  | 7.45k  |     if (!m_oFC.GetParentXPath().empty())  | 
91  | 2.58k  |     { | 
92  | 2.58k  |         poLayerDescFeature->SetField(szLAYER_CATEGORY, szJUNCTION_TABLE);  | 
93  | 2.58k  |     }  | 
94  | 4.87k  |     else  | 
95  | 4.87k  |     { | 
96  | 4.87k  |         poLayerDescFeature->SetField(szLAYER_XPATH, m_oFC.GetXPath());  | 
97  |  |  | 
98  | 4.87k  |         poLayerDescFeature->SetField(szLAYER_CATEGORY, m_oFC.IsTopLevelElt()  | 
99  | 4.87k  |                                                            ? szTOP_LEVEL_ELEMENT  | 
100  | 4.87k  |                                                            : szNESTED_ELEMENT);  | 
101  |  |  | 
102  | 4.87k  |         if (m_nIDFieldIdx >= 0)  | 
103  | 4.87k  |         { | 
104  | 4.87k  |             poLayerDescFeature->SetField(  | 
105  | 4.87k  |                 szLAYER_PKID_NAME,  | 
106  | 4.87k  |                 m_poFeatureDefn->GetFieldDefn(m_nIDFieldIdx)->GetNameRef());  | 
107  | 4.87k  |         }  | 
108  |  |  | 
109  |  |         // If we are a child class, then add a field to reference the parent.  | 
110  | 4.87k  |         if (m_poParentLayer != nullptr)  | 
111  | 2.11k  |         { | 
112  | 2.11k  |             CPLString osFieldName(szPARENT_PREFIX);  | 
113  | 2.11k  |             osFieldName += m_poParentLayer->GetLayerDefn()  | 
114  | 2.11k  |                                ->GetFieldDefn(m_poParentLayer->GetIDFieldIdx())  | 
115  | 2.11k  |                                ->GetNameRef();  | 
116  | 2.11k  |             poLayerDescFeature->SetField(szLAYER_PARENT_PKID_NAME,  | 
117  | 2.11k  |                                          osFieldName.c_str());  | 
118  | 2.11k  |         }  | 
119  |  |  | 
120  | 4.87k  |         if (!m_oFC.GetDocumentation().empty())  | 
121  | 0  |         { | 
122  | 0  |             poLayerDescFeature->SetField(szLAYER_DOCUMENTATION,  | 
123  | 0  |                                          m_oFC.GetDocumentation());  | 
124  | 0  |         }  | 
125  | 4.87k  |     }  | 
126  | 7.45k  |     CPL_IGNORE_RET_VAL(  | 
127  | 7.45k  |         poLayersMetadataLayer->CreateFeature(poLayerDescFeature));  | 
128  | 7.45k  |     delete poLayerDescFeature;  | 
129  | 7.45k  | }  | 
130  |  |  | 
131  |  | /************************************************************************/  | 
132  |  | /*                            OGRGMLASLayer()                           */  | 
133  |  | /************************************************************************/  | 
134  |  |  | 
135  |  | OGRGMLASLayer::OGRGMLASLayer(const char *pszLayerName)  | 
136  | 2.22k  |     : m_bLayerDefnFinalized(true),  | 
137  | 2.22k  |       m_poFeatureDefn(new OGRFeatureDefn(pszLayerName))  | 
138  |  |  | 
139  | 2.22k  | { | 
140  | 2.22k  |     m_poFeatureDefn->SetGeomType(wkbNone);  | 
141  | 2.22k  |     m_poFeatureDefn->Reference();  | 
142  |  |  | 
143  | 2.22k  |     SetDescription(m_poFeatureDefn->GetName());  | 
144  | 2.22k  | }  | 
145  |  |  | 
146  |  | /************************************************************************/  | 
147  |  | /*                        GetSWEChildAndType()                          */  | 
148  |  | /************************************************************************/  | 
149  |  |  | 
150  |  | static CPLXMLNode *GetSWEChildAndType(CPLXMLNode *psNode, OGRFieldType &eType,  | 
151  |  |                                       OGRFieldSubType &eSubType)  | 
152  | 4.24k  | { | 
153  | 4.24k  |     eType = OFTString;  | 
154  | 4.24k  |     eSubType = OFSTNone;  | 
155  | 4.24k  |     CPLXMLNode *psChildNode = nullptr;  | 
156  | 4.24k  |     if ((psChildNode = CPLGetXMLNode(psNode, "Time")) != nullptr)  | 
157  | 2.07k  |     { | 
158  | 2.07k  |         eType = OFTDateTime;  | 
159  | 2.07k  |     }  | 
160  | 2.16k  |     else if ((psChildNode = CPLGetXMLNode(psNode, "Quantity")) != nullptr)  | 
161  | 1.32k  |     { | 
162  | 1.32k  |         eType = OFTReal;  | 
163  | 1.32k  |     }  | 
164  | 847  |     else if ((psChildNode = CPLGetXMLNode(psNode, "Category")) != nullptr)  | 
165  | 426  |     { | 
166  | 426  |         eType = OFTString;  | 
167  | 426  |     }  | 
168  | 421  |     else if ((psChildNode = CPLGetXMLNode(psNode, "Count")) != nullptr)  | 
169  | 7  |     { | 
170  | 7  |         eType = OFTInteger;  | 
171  | 7  |     }  | 
172  | 414  |     else if ((psChildNode = CPLGetXMLNode(psNode, "Text")) != nullptr)  | 
173  | 152  |     { | 
174  | 152  |         eType = OFTString;  | 
175  | 152  |     }  | 
176  | 262  |     else if ((psChildNode = CPLGetXMLNode(psNode, "Boolean")) != nullptr)  | 
177  | 145  |     { | 
178  | 145  |         eType = OFTInteger;  | 
179  | 145  |         eSubType = OFSTBoolean;  | 
180  | 145  |     }  | 
181  | 4.24k  |     return psChildNode;  | 
182  | 4.24k  | }  | 
183  |  |  | 
184  |  | /************************************************************************/  | 
185  |  | /*              ProcessDataRecordOfDataArrayCreateFields()               */  | 
186  |  | /************************************************************************/  | 
187  |  |  | 
188  |  | void OGRGMLASLayer::ProcessDataRecordOfDataArrayCreateFields(  | 
189  |  |     OGRGMLASLayer *poParentLayer, CPLXMLNode *psDataRecord,  | 
190  |  |     OGRLayer *poFieldsMetadataLayer)  | 
191  | 2.22k  | { | 
192  | 2.22k  |     { | 
193  | 2.22k  |         CPLString osFieldName(szPARENT_PREFIX);  | 
194  | 2.22k  |         osFieldName += poParentLayer->GetLayerDefn()  | 
195  | 2.22k  |                            ->GetFieldDefn(poParentLayer->GetIDFieldIdx())  | 
196  | 2.22k  |                            ->GetNameRef();  | 
197  | 2.22k  |         OGRFieldDefn oFieldDefn(osFieldName, OFTString);  | 
198  | 2.22k  |         oFieldDefn.SetNullable(false);  | 
199  | 2.22k  |         m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
200  | 2.22k  |     }  | 
201  |  |  | 
202  | 12.9k  |     for (CPLXMLNode *psIter = psDataRecord->psChild; psIter != nullptr;  | 
203  | 10.7k  |          psIter = psIter->psNext)  | 
204  | 10.7k  |     { | 
205  | 10.7k  |         if (psIter->eType == CXT_Element &&  | 
206  | 10.7k  |             strcmp(psIter->pszValue, "field") == 0)  | 
207  | 4.24k  |         { | 
208  | 4.24k  |             const char *pszName = CPLGetXMLValue(psIter, "name", "");  | 
209  | 4.24k  |             OGRFieldDefn oFieldDefn(CPLString(pszName).tolower(), OFTString);  | 
210  | 4.24k  |             OGRFieldType eType;  | 
211  | 4.24k  |             OGRFieldSubType eSubType;  | 
212  | 4.24k  |             CPLXMLNode *psNode = GetSWEChildAndType(psIter, eType, eSubType);  | 
213  | 4.24k  |             oFieldDefn.SetType(eType);  | 
214  | 4.24k  |             oFieldDefn.SetSubType(eSubType);  | 
215  | 4.24k  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
216  |  |  | 
217  |  |             // Register field in _ogr_fields_metadata  | 
218  | 4.24k  |             OGRFeature *poFieldDescFeature =  | 
219  | 4.24k  |                 new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
220  | 4.24k  |             poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
221  | 4.24k  |             m_nMaxFieldIndex = m_poFeatureDefn->GetFieldCount() - 1;  | 
222  | 4.24k  |             poFieldDescFeature->SetField(szFIELD_INDEX, m_nMaxFieldIndex);  | 
223  | 4.24k  |             poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());  | 
224  | 4.24k  |             if (psNode)  | 
225  | 4.12k  |             { | 
226  | 4.12k  |                 poFieldDescFeature->SetField(szFIELD_TYPE, psNode->pszValue);  | 
227  | 4.12k  |             }  | 
228  | 4.24k  |             poFieldDescFeature->SetField(szFIELD_IS_LIST, 0);  | 
229  | 4.24k  |             poFieldDescFeature->SetField(szFIELD_MIN_OCCURS, 0);  | 
230  | 4.24k  |             poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, 1);  | 
231  | 4.24k  |             poFieldDescFeature->SetField(szFIELD_CATEGORY, szSWE_FIELD);  | 
232  | 4.24k  |             if (psNode)  | 
233  | 4.12k  |             { | 
234  | 4.12k  |                 char *pszXML = CPLSerializeXMLTree(psNode);  | 
235  | 4.12k  |                 poFieldDescFeature->SetField(szFIELD_DOCUMENTATION, pszXML);  | 
236  | 4.12k  |                 CPLFree(pszXML);  | 
237  | 4.12k  |             }  | 
238  | 4.24k  |             CPL_IGNORE_RET_VAL(  | 
239  | 4.24k  |                 poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
240  | 4.24k  |             delete poFieldDescFeature;  | 
241  | 4.24k  |         }  | 
242  | 10.7k  |     }  | 
243  | 2.22k  | }  | 
244  |  |  | 
245  |  | /************************************************************************/  | 
246  |  | /*                ProcessDataRecordCreateFields()                       */  | 
247  |  | /************************************************************************/  | 
248  |  |  | 
249  |  | void OGRGMLASLayer::ProcessDataRecordCreateFields(  | 
250  |  |     CPLXMLNode *psDataRecord, const std::vector<OGRFeature *> &apoFeatures,  | 
251  |  |     OGRLayer *poFieldsMetadataLayer)  | 
252  | 0  | { | 
253  | 0  |     for (CPLXMLNode *psIter = psDataRecord->psChild; psIter != nullptr;  | 
254  | 0  |          psIter = psIter->psNext)  | 
255  | 0  |     { | 
256  | 0  |         if (psIter->eType == CXT_Element &&  | 
257  | 0  |             strcmp(psIter->pszValue, "field") == 0)  | 
258  | 0  |         { | 
259  | 0  |             const char *pszName = CPLGetXMLValue(psIter, "name", "");  | 
260  | 0  |             CPLString osName = CPLString(pszName).tolower();  | 
261  | 0  |             OGRFieldDefn oFieldDefn(osName, OFTString);  | 
262  | 0  |             OGRFieldType eType;  | 
263  | 0  |             OGRFieldSubType eSubType;  | 
264  | 0  |             CPLXMLNode *psChildNode =  | 
265  | 0  |                 GetSWEChildAndType(psIter, eType, eSubType);  | 
266  | 0  |             oFieldDefn.SetType(eType);  | 
267  | 0  |             oFieldDefn.SetSubType(eSubType);  | 
268  | 0  |             if (psChildNode != nullptr &&  | 
269  | 0  |                 m_oMapSWEFieldToOGRFieldName.find(osName) ==  | 
270  | 0  |                     m_oMapSWEFieldToOGRFieldName.end())  | 
271  | 0  |             { | 
272  | 0  |                 const int nValidFields = m_poFeatureDefn->GetFieldCount();  | 
273  |  | 
  | 
274  | 0  |                 CPLString osSWEField(osName);  | 
275  | 0  |                 if (m_poFeatureDefn->GetFieldIndex(osName) >= 0)  | 
276  | 0  |                     osName = "swe_field_" + osName;  | 
277  | 0  |                 m_oMapSWEFieldToOGRFieldName[osSWEField] = osName;  | 
278  | 0  |                 oFieldDefn.SetName((osName + "_value").c_str());  | 
279  | 0  |                 m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
280  |  |  | 
281  |  |                 // Register field in _ogr_fields_metadata  | 
282  | 0  |                 OGRFeature *poFieldDescFeature =  | 
283  | 0  |                     new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
284  | 0  |                 poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
285  | 0  |                 m_nMaxFieldIndex++;  | 
286  | 0  |                 poFieldDescFeature->SetField(szFIELD_INDEX, m_nMaxFieldIndex);  | 
287  | 0  |                 poFieldDescFeature->SetField(szFIELD_NAME,  | 
288  | 0  |                                              oFieldDefn.GetNameRef());  | 
289  | 0  |                 poFieldDescFeature->SetField(szFIELD_TYPE,  | 
290  | 0  |                                              psChildNode->pszValue);  | 
291  | 0  |                 poFieldDescFeature->SetField(szFIELD_IS_LIST, 0);  | 
292  | 0  |                 poFieldDescFeature->SetField(szFIELD_MIN_OCCURS, 0);  | 
293  | 0  |                 poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, 1);  | 
294  | 0  |                 poFieldDescFeature->SetField(szFIELD_CATEGORY, szSWE_FIELD);  | 
295  | 0  |                 { | 
296  | 0  |                     CPLXMLNode *psDupTree = CPLCloneXMLTree(psChildNode);  | 
297  | 0  |                     CPLXMLNode *psValue = CPLGetXMLNode(psDupTree, "value");  | 
298  | 0  |                     if (psValue != nullptr)  | 
299  | 0  |                     { | 
300  | 0  |                         CPLRemoveXMLChild(psDupTree, psValue);  | 
301  | 0  |                         CPLDestroyXMLNode(psValue);  | 
302  | 0  |                     }  | 
303  | 0  |                     char *pszXML = CPLSerializeXMLTree(psDupTree);  | 
304  | 0  |                     CPLDestroyXMLNode(psDupTree);  | 
305  | 0  |                     poFieldDescFeature->SetField(szFIELD_DOCUMENTATION, pszXML);  | 
306  | 0  |                     CPLFree(pszXML);  | 
307  | 0  |                 }  | 
308  | 0  |                 CPL_IGNORE_RET_VAL(  | 
309  | 0  |                     poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
310  | 0  |                 delete poFieldDescFeature;  | 
311  |  | 
  | 
312  | 0  |                 for (CPLXMLNode *psIter2 = psChildNode->psChild;  | 
313  | 0  |                      psIter2 != nullptr; psIter2 = psIter2->psNext)  | 
314  | 0  |                 { | 
315  | 0  |                     if (psIter2->eType == CXT_Element &&  | 
316  | 0  |                         strcmp(psIter2->pszValue, "value") != 0)  | 
317  | 0  |                     { | 
318  | 0  |                         const CPLString osName2 =  | 
319  | 0  |                             CPLString(osName + "_" + psIter2->pszValue)  | 
320  | 0  |                                 .tolower();  | 
321  | 0  |                         for (CPLXMLNode *psIter3 = psIter2->psChild;  | 
322  | 0  |                              psIter3 != nullptr; psIter3 = psIter3->psNext)  | 
323  | 0  |                         { | 
324  | 0  |                             if (psIter3->eType == CXT_Attribute)  | 
325  | 0  |                             { | 
326  | 0  |                                 const char *pszValue = psIter3->pszValue;  | 
327  | 0  |                                 const char *pszColon = strchr(pszValue, ':');  | 
328  | 0  |                                 if (pszColon)  | 
329  | 0  |                                     pszValue = pszColon + 1;  | 
330  | 0  |                                 OGRFieldDefn oFieldDefn2(  | 
331  | 0  |                                     CPLString(osName2 + "_" + pszValue)  | 
332  | 0  |                                         .tolower(),  | 
333  | 0  |                                     OFTString);  | 
334  | 0  |                                 m_poFeatureDefn->AddFieldDefn(&oFieldDefn2);  | 
335  | 0  |                             }  | 
336  | 0  |                             else if (psIter3->eType == CXT_Text)  | 
337  | 0  |                             { | 
338  | 0  |                                 OGRFieldDefn oFieldDefn2(osName2, OFTString);  | 
339  | 0  |                                 m_poFeatureDefn->AddFieldDefn(&oFieldDefn2);  | 
340  | 0  |                             }  | 
341  | 0  |                         }  | 
342  | 0  |                     }  | 
343  | 0  |                 }  | 
344  |  | 
  | 
345  | 0  |                 int *panRemap = static_cast<int *>(  | 
346  | 0  |                     CPLMalloc(sizeof(int) * m_poFeatureDefn->GetFieldCount()));  | 
347  | 0  |                 for (int i = 0; i < m_poFeatureDefn->GetFieldCount(); ++i)  | 
348  | 0  |                 { | 
349  | 0  |                     if (i < nValidFields)  | 
350  | 0  |                         panRemap[i] = i;  | 
351  | 0  |                     else  | 
352  | 0  |                         panRemap[i] = -1;  | 
353  | 0  |                 }  | 
354  |  | 
  | 
355  | 0  |                 for (size_t i = 0; i < apoFeatures.size(); i++)  | 
356  | 0  |                 { | 
357  | 0  |                     apoFeatures[i]->RemapFields(nullptr, panRemap);  | 
358  | 0  |                 }  | 
359  |  | 
  | 
360  | 0  |                 CPLFree(panRemap);  | 
361  | 0  |             }  | 
362  | 0  |         }  | 
363  | 0  |     }  | 
364  | 0  | }  | 
365  |  |  | 
366  |  | /************************************************************************/  | 
367  |  | /*                             SetSWEValue()                            */  | 
368  |  | /************************************************************************/  | 
369  |  |  | 
370  |  | static void SetSWEValue(OGRFeature *poFeature, const CPLString &osFieldName,  | 
371  |  |                         const char *pszValue)  | 
372  | 0  | { | 
373  | 0  |     int iField = poFeature->GetDefnRef()->GetFieldIndex(osFieldName);  | 
374  | 0  |     OGRFieldDefn *poFieldDefn = poFeature->GetFieldDefnRef(iField);  | 
375  | 0  |     OGRFieldType eType(poFieldDefn->GetType());  | 
376  | 0  |     OGRFieldSubType eSubType(poFieldDefn->GetSubType());  | 
377  | 0  |     if (eType == OFTInteger && eSubType == OFSTBoolean)  | 
378  | 0  |     { | 
379  | 0  |         poFeature->SetField(  | 
380  | 0  |             iField, EQUAL(pszValue, "1") || EQUAL(pszValue, "True") ? 1 : 0);  | 
381  | 0  |     }  | 
382  | 0  |     else  | 
383  | 0  |     { | 
384  | 0  |         poFeature->SetField(iField, pszValue);  | 
385  | 0  |     }  | 
386  | 0  | }  | 
387  |  |  | 
388  |  | /************************************************************************/  | 
389  |  | /*                    ProcessDataRecordFillFeature()                    */  | 
390  |  | /************************************************************************/  | 
391  |  |  | 
392  |  | void OGRGMLASLayer::ProcessDataRecordFillFeature(CPLXMLNode *psDataRecord,  | 
393  |  |                                                  OGRFeature *poFeature)  | 
394  | 0  | { | 
395  | 0  |     for (CPLXMLNode *psIter = psDataRecord->psChild; psIter != nullptr;  | 
396  | 0  |          psIter = psIter->psNext)  | 
397  | 0  |     { | 
398  | 0  |         if (psIter->eType == CXT_Element &&  | 
399  | 0  |             strcmp(psIter->pszValue, "field") == 0)  | 
400  | 0  |         { | 
401  | 0  |             const char *pszName = CPLGetXMLValue(psIter, "name", "");  | 
402  | 0  |             CPLString osName = CPLString(pszName).tolower();  | 
403  | 0  |             OGRFieldDefn oFieldDefn(osName, OFTString);  | 
404  | 0  |             OGRFieldType eType;  | 
405  | 0  |             OGRFieldSubType eSubType;  | 
406  | 0  |             CPLXMLNode *psChildNode =  | 
407  | 0  |                 GetSWEChildAndType(psIter, eType, eSubType);  | 
408  | 0  |             oFieldDefn.SetType(eType);  | 
409  | 0  |             oFieldDefn.SetSubType(eSubType);  | 
410  | 0  |             if (psChildNode == nullptr)  | 
411  | 0  |                 continue;  | 
412  | 0  |             const auto oIter = m_oMapSWEFieldToOGRFieldName.find(osName);  | 
413  | 0  |             CPLAssert(oIter != m_oMapSWEFieldToOGRFieldName.end());  | 
414  | 0  |             osName = oIter->second;  | 
415  | 0  |             for (CPLXMLNode *psIter2 = psChildNode->psChild; psIter2 != nullptr;  | 
416  | 0  |                  psIter2 = psIter2->psNext)  | 
417  | 0  |             { | 
418  | 0  |                 if (psIter2->eType == CXT_Element)  | 
419  | 0  |                 { | 
420  | 0  |                     const CPLString osName2 =  | 
421  | 0  |                         CPLString(osName + "_" + psIter2->pszValue).tolower();  | 
422  | 0  |                     for (CPLXMLNode *psIter3 = psIter2->psChild;  | 
423  | 0  |                          psIter3 != nullptr; psIter3 = psIter3->psNext)  | 
424  | 0  |                     { | 
425  | 0  |                         if (psIter3->eType == CXT_Attribute)  | 
426  | 0  |                         { | 
427  | 0  |                             const char *pszValue = psIter3->pszValue;  | 
428  | 0  |                             const char *pszColon = strchr(pszValue, ':');  | 
429  | 0  |                             if (pszColon)  | 
430  | 0  |                                 pszValue = pszColon + 1;  | 
431  | 0  |                             SetSWEValue(  | 
432  | 0  |                                 poFeature,  | 
433  | 0  |                                 CPLString(osName2 + "_" + pszValue).tolower(),  | 
434  | 0  |                                 psIter3->psChild->pszValue);  | 
435  | 0  |                         }  | 
436  | 0  |                         else if (psIter3->eType == CXT_Text)  | 
437  | 0  |                         { | 
438  | 0  |                             SetSWEValue(poFeature, osName2, psIter3->pszValue);  | 
439  | 0  |                         }  | 
440  | 0  |                     }  | 
441  | 0  |                 }  | 
442  | 0  |             }  | 
443  | 0  |         }  | 
444  | 0  |     }  | 
445  | 0  | }  | 
446  |  |  | 
447  |  | /************************************************************************/  | 
448  |  | /*                             PostInit()                               */  | 
449  |  | /************************************************************************/  | 
450  |  |  | 
451  |  | void OGRGMLASLayer::PostInit(bool bIncludeGeometryXML)  | 
452  | 7.45k  | { | 
453  | 7.45k  |     const std::vector<GMLASField> &oFields = m_oFC.GetFields();  | 
454  |  |  | 
455  | 7.45k  |     OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();  | 
456  | 7.45k  |     OGRLayer *poRelationshipsLayer = m_poDS->GetRelationshipsLayer();  | 
457  |  |  | 
458  |  |     // Is it a junction table ?  | 
459  | 7.45k  |     if (!m_oFC.GetParentXPath().empty())  | 
460  | 2.58k  |     { | 
461  | 2.58k  |         { | 
462  | 2.58k  |             OGRFieldDefn oFieldDefn(szOCCURRENCE, OFTInteger);  | 
463  | 2.58k  |             oFieldDefn.SetNullable(false);  | 
464  | 2.58k  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
465  |  |  | 
466  | 2.58k  |             OGRFeature *poFieldDescFeature =  | 
467  | 2.58k  |                 new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
468  | 2.58k  |             poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
469  | 2.58k  |             poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());  | 
470  | 2.58k  |             CPL_IGNORE_RET_VAL(  | 
471  | 2.58k  |                 poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
472  | 2.58k  |             delete poFieldDescFeature;  | 
473  | 2.58k  |         }  | 
474  |  |  | 
475  | 2.58k  |         { | 
476  | 2.58k  |             OGRFieldDefn oFieldDefn(szPARENT_PKID, OFTString);  | 
477  | 2.58k  |             oFieldDefn.SetNullable(false);  | 
478  | 2.58k  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
479  |  |  | 
480  | 2.58k  |             OGRFeature *poFieldDescFeature =  | 
481  | 2.58k  |                 new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
482  | 2.58k  |             poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
483  | 2.58k  |             poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());  | 
484  | 2.58k  |             CPL_IGNORE_RET_VAL(  | 
485  | 2.58k  |                 poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
486  | 2.58k  |             delete poFieldDescFeature;  | 
487  | 2.58k  |         }  | 
488  | 2.58k  |         { | 
489  | 2.58k  |             OGRFieldDefn oFieldDefn(szCHILD_PKID, OFTString);  | 
490  | 2.58k  |             oFieldDefn.SetNullable(false);  | 
491  | 2.58k  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
492  |  |  | 
493  | 2.58k  |             OGRFeature *poFieldDescFeature =  | 
494  | 2.58k  |                 new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
495  | 2.58k  |             poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
496  | 2.58k  |             poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());  | 
497  | 2.58k  |             CPL_IGNORE_RET_VAL(  | 
498  | 2.58k  |                 poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
499  | 2.58k  |             delete poFieldDescFeature;  | 
500  | 2.58k  |         }  | 
501  |  |  | 
502  | 2.58k  |         return;  | 
503  | 2.58k  |     }  | 
504  |  |  | 
505  |  |     // If we are a child class, then add a field to reference the parent.  | 
506  | 4.87k  |     if (m_poParentLayer != nullptr)  | 
507  | 2.11k  |     { | 
508  | 2.11k  |         CPLString osFieldName(szPARENT_PREFIX);  | 
509  | 2.11k  |         osFieldName += m_poParentLayer->GetLayerDefn()  | 
510  | 2.11k  |                            ->GetFieldDefn(m_poParentLayer->GetIDFieldIdx())  | 
511  | 2.11k  |                            ->GetNameRef();  | 
512  | 2.11k  |         OGRFieldDefn oFieldDefn(osFieldName, OFTString);  | 
513  | 2.11k  |         oFieldDefn.SetNullable(false);  | 
514  | 2.11k  |         m_nParentIDFieldIdx = m_poFeatureDefn->GetFieldCount();  | 
515  | 2.11k  |         m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
516  | 2.11k  |     }  | 
517  |  |  | 
518  | 4.87k  |     int nFieldIndex = 0;  | 
519  | 92.7k  |     for (int i = 0; i < static_cast<int>(oFields.size()); i++)  | 
520  | 87.8k  |     { | 
521  | 87.8k  |         OGRGMLASLayer *poRelatedLayer = nullptr;  | 
522  | 87.8k  |         const GMLASField &oField(oFields[i]);  | 
523  |  |  | 
524  | 87.8k  |         m_oMapFieldXPathToFCFieldIdx[oField.GetXPath()] = i;  | 
525  | 87.8k  |         if (oField.IsIgnored())  | 
526  | 0  |             continue;  | 
527  |  |  | 
528  | 87.8k  |         const GMLASField::Category eCategory(oField.GetCategory());  | 
529  | 87.8k  |         if (!oField.GetRelatedClassXPath().empty())  | 
530  | 19.3k  |         { | 
531  | 19.3k  |             poRelatedLayer =  | 
532  | 19.3k  |                 m_poDS->GetLayerByXPath(oField.GetRelatedClassXPath());  | 
533  | 19.3k  |             if (poRelatedLayer != nullptr)  | 
534  | 19.3k  |             { | 
535  | 19.3k  |                 OGRFeature *poRelationshipsFeature =  | 
536  | 19.3k  |                     new OGRFeature(poRelationshipsLayer->GetLayerDefn());  | 
537  | 19.3k  |                 poRelationshipsFeature->SetField(szPARENT_LAYER, GetName());  | 
538  | 19.3k  |                 poRelationshipsFeature->SetField(  | 
539  | 19.3k  |                     szPARENT_PKID, GetLayerDefn()  | 
540  | 19.3k  |                                        ->GetFieldDefn(GetIDFieldIdx())  | 
541  | 19.3k  |                                        ->GetNameRef());  | 
542  | 19.3k  |                 if (!oField.GetName().empty())  | 
543  | 19.3k  |                 { | 
544  | 19.3k  |                     poRelationshipsFeature->SetField(szPARENT_ELEMENT_NAME,  | 
545  | 19.3k  |                                                      oField.GetName());  | 
546  | 19.3k  |                 }  | 
547  | 19.3k  |                 poRelationshipsFeature->SetField(szCHILD_LAYER,  | 
548  | 19.3k  |                                                  poRelatedLayer->GetName());  | 
549  | 19.3k  |                 if (eCategory ==  | 
550  | 19.3k  |                         GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||  | 
551  | 19.3k  |                     eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK)  | 
552  | 17.2k  |                 { | 
553  | 17.2k  |                     poRelationshipsFeature->SetField(  | 
554  | 17.2k  |                         szCHILD_PKID,  | 
555  | 17.2k  |                         poRelatedLayer->GetLayerDefn()  | 
556  | 17.2k  |                             ->GetFieldDefn(poRelatedLayer->GetIDFieldIdx())  | 
557  | 17.2k  |                             ->GetNameRef());  | 
558  | 17.2k  |                 }  | 
559  | 2.11k  |                 else  | 
560  | 2.11k  |                 { | 
561  | 2.11k  |                     CPLAssert(eCategory ==  | 
562  | 2.11k  |                                   GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||  | 
563  | 2.11k  |                               eCategory == GMLASField::GROUP);  | 
564  |  |  | 
565  | 2.11k  |                     poRelationshipsFeature->SetField(  | 
566  | 2.11k  |                         szCHILD_PKID, (CPLString(szPARENT_PREFIX) +  | 
567  | 2.11k  |                                        GetLayerDefn()  | 
568  | 2.11k  |                                            ->GetFieldDefn(GetIDFieldIdx())  | 
569  | 2.11k  |                                            ->GetNameRef())  | 
570  | 2.11k  |                                           .c_str());  | 
571  | 2.11k  |                 }  | 
572  | 19.3k  |                 CPL_IGNORE_RET_VAL(poRelationshipsLayer->CreateFeature(  | 
573  | 19.3k  |                     poRelationshipsFeature));  | 
574  | 19.3k  |                 delete poRelationshipsFeature;  | 
575  | 19.3k  |             }  | 
576  | 0  |             else  | 
577  | 0  |             { | 
578  | 0  |                 CPLDebug("GMLAS", "Cannot find class matching %s", | 
579  | 0  |                          oField.GetRelatedClassXPath().c_str());  | 
580  | 0  |             }  | 
581  | 19.3k  |         }  | 
582  |  |  | 
583  | 87.8k  |         OGRFeature *poFieldDescFeature =  | 
584  | 87.8k  |             new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
585  | 87.8k  |         poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
586  |  |  | 
587  | 87.8k  |         ++nFieldIndex;  | 
588  | 87.8k  |         m_nMaxFieldIndex = nFieldIndex;  | 
589  | 87.8k  |         poFieldDescFeature->SetField(szFIELD_INDEX, nFieldIndex);  | 
590  |  |  | 
591  | 87.8k  |         if (oField.GetName().empty())  | 
592  | 0  |         { | 
593  | 0  |             CPLAssert(eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||  | 
594  | 0  |                       eCategory == GMLASField::GROUP);  | 
595  | 0  |         }  | 
596  | 87.8k  |         else  | 
597  | 87.8k  |         { | 
598  | 87.8k  |             poFieldDescFeature->SetField(szFIELD_NAME,  | 
599  | 87.8k  |                                          oField.GetName().c_str());  | 
600  | 87.8k  |         }  | 
601  | 87.8k  |         if (!oField.GetXPath().empty())  | 
602  | 87.8k  |         { | 
603  | 87.8k  |             poFieldDescFeature->SetField(szFIELD_XPATH,  | 
604  | 87.8k  |                                          oField.GetXPath().c_str());  | 
605  | 87.8k  |         }  | 
606  | 0  |         else if (!oField.GetAlternateXPaths().empty())  | 
607  | 0  |         { | 
608  | 0  |             CPLString osXPath;  | 
609  | 0  |             const std::vector<CPLString> &aoXPaths =  | 
610  | 0  |                 oField.GetAlternateXPaths();  | 
611  | 0  |             for (size_t j = 0; j < aoXPaths.size(); j++)  | 
612  | 0  |             { | 
613  | 0  |                 if (j != 0)  | 
614  | 0  |                     osXPath += ",";  | 
615  | 0  |                 osXPath += aoXPaths[j];  | 
616  | 0  |             }  | 
617  | 0  |             poFieldDescFeature->SetField(szFIELD_XPATH, osXPath.c_str());  | 
618  | 0  |         }  | 
619  | 87.8k  |         if (oField.GetTypeName().empty())  | 
620  | 4.70k  |         { | 
621  | 4.70k  |             CPLAssert(  | 
622  | 4.70k  |                 eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||  | 
623  | 4.70k  |                 eCategory ==  | 
624  | 4.70k  |                     GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||  | 
625  | 4.70k  |                 eCategory == GMLASField::GROUP);  | 
626  | 4.70k  |         }  | 
627  | 83.1k  |         else  | 
628  | 83.1k  |         { | 
629  | 83.1k  |             poFieldDescFeature->SetField(szFIELD_TYPE,  | 
630  | 83.1k  |                                          oField.GetTypeName().c_str());  | 
631  | 83.1k  |         }  | 
632  | 87.8k  |         poFieldDescFeature->SetField(szFIELD_IS_LIST,  | 
633  | 87.8k  |                                      static_cast<int>(oField.IsList()));  | 
634  | 87.8k  |         if (oField.GetMinOccurs() != -1)  | 
635  | 57.1k  |         { | 
636  | 57.1k  |             poFieldDescFeature->SetField(szFIELD_MIN_OCCURS,  | 
637  | 57.1k  |                                          oField.GetMinOccurs());  | 
638  | 57.1k  |         }  | 
639  | 87.8k  |         if (oField.GetMaxOccurs() == MAXOCCURS_UNLIMITED)  | 
640  | 4.64k  |         { | 
641  | 4.64k  |             poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, INT_MAX);  | 
642  | 4.64k  |         }  | 
643  | 83.1k  |         else if (oField.GetMaxOccurs() != -1)  | 
644  | 52.3k  |         { | 
645  | 52.3k  |             poFieldDescFeature->SetField(szFIELD_MAX_OCCURS,  | 
646  | 52.3k  |                                          oField.GetMaxOccurs());  | 
647  | 52.3k  |         }  | 
648  | 87.8k  |         if (oField.GetMaxOccurs() == MAXOCCURS_UNLIMITED ||  | 
649  | 87.8k  |             oField.GetMaxOccurs() > 1)  | 
650  | 4.70k  |         { | 
651  | 4.70k  |             poFieldDescFeature->SetField(szFIELD_REPETITION_ON_SEQUENCE,  | 
652  | 4.70k  |                                          oField.GetRepetitionOnSequence() ? 1  | 
653  | 4.70k  |                                                                           : 0);  | 
654  | 4.70k  |         }  | 
655  | 87.8k  |         if (!oField.GetFixedValue().empty())  | 
656  | 1  |         { | 
657  | 1  |             poFieldDescFeature->SetField(szFIELD_FIXED_VALUE,  | 
658  | 1  |                                          oField.GetFixedValue());  | 
659  | 1  |         }  | 
660  | 87.8k  |         if (!oField.GetDefaultValue().empty())  | 
661  | 0  |         { | 
662  | 0  |             poFieldDescFeature->SetField(szFIELD_DEFAULT_VALUE,  | 
663  | 0  |                                          oField.GetDefaultValue());  | 
664  | 0  |         }  | 
665  | 87.8k  |         switch (eCategory)  | 
666  | 87.8k  |         { | 
667  | 68.5k  |             case GMLASField::REGULAR:  | 
668  | 68.5k  |                 poFieldDescFeature->SetField(szFIELD_CATEGORY, szREGULAR);  | 
669  | 68.5k  |                 break;  | 
670  | 2.11k  |             case GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK:  | 
671  | 2.11k  |                 poFieldDescFeature->SetField(szFIELD_CATEGORY,  | 
672  | 2.11k  |                                              szPATH_TO_CHILD_ELEMENT_NO_LINK);  | 
673  | 2.11k  |                 break;  | 
674  | 14.6k  |             case GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK:  | 
675  | 14.6k  |                 poFieldDescFeature->SetField(szFIELD_CATEGORY,  | 
676  | 14.6k  |                                              szPATH_TO_CHILD_ELEMENT_WITH_LINK);  | 
677  | 14.6k  |                 break;  | 
678  | 2.58k  |             case GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE:  | 
679  | 2.58k  |                 poFieldDescFeature->SetField(  | 
680  | 2.58k  |                     szFIELD_CATEGORY,  | 
681  | 2.58k  |                     szPATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE);  | 
682  | 2.58k  |                 break;  | 
683  | 0  |             case GMLASField::GROUP:  | 
684  | 0  |                 poFieldDescFeature->SetField(szFIELD_CATEGORY, szGROUP);  | 
685  | 0  |                 break;  | 
686  | 0  |             default:  | 
687  | 0  |                 CPLAssert(FALSE);  | 
688  | 0  |                 break;  | 
689  | 87.8k  |         }  | 
690  | 87.8k  |         if (poRelatedLayer != nullptr)  | 
691  | 19.3k  |         { | 
692  | 19.3k  |             poFieldDescFeature->SetField(szFIELD_RELATED_LAYER,  | 
693  | 19.3k  |                                          poRelatedLayer->GetName());  | 
694  | 19.3k  |         }  | 
695  |  |  | 
696  | 87.8k  |         if (eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE)  | 
697  | 2.58k  |         { | 
698  | 2.58k  |             const CPLString &osAbstractElementXPath(  | 
699  | 2.58k  |                 oField.GetAbstractElementXPath());  | 
700  | 2.58k  |             const CPLString &osNestedXPath(oField.GetRelatedClassXPath());  | 
701  | 2.58k  |             CPLAssert(!osAbstractElementXPath.empty());  | 
702  | 2.58k  |             CPLAssert(!osNestedXPath.empty());  | 
703  |  |  | 
704  | 2.58k  |             OGRGMLASLayer *poJunctionLayer = m_poDS->GetLayerByXPath(  | 
705  | 2.58k  |                 osAbstractElementXPath + "|" + osNestedXPath);  | 
706  | 2.58k  |             if (poJunctionLayer != nullptr)  | 
707  | 2.58k  |             { | 
708  | 2.58k  |                 poFieldDescFeature->SetField(szFIELD_JUNCTION_LAYER,  | 
709  | 2.58k  |                                              poJunctionLayer->GetName());  | 
710  | 2.58k  |             }  | 
711  | 2.58k  |         }  | 
712  |  |  | 
713  | 87.8k  |         if (!oField.GetDocumentation().empty())  | 
714  | 0  |         { | 
715  | 0  |             poFieldDescFeature->SetField(szFIELD_DOCUMENTATION,  | 
716  | 0  |                                          oField.GetDocumentation());  | 
717  | 0  |         }  | 
718  |  |  | 
719  | 87.8k  |         CPL_IGNORE_RET_VAL(  | 
720  | 87.8k  |             poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
721  | 87.8k  |         delete poFieldDescFeature;  | 
722  |  |  | 
723  |  |         // Check whether the field is OGR instanciable  | 
724  | 87.8k  |         if (eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||  | 
725  | 87.8k  |             eCategory ==  | 
726  | 85.7k  |                 GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||  | 
727  | 87.8k  |             eCategory == GMLASField::GROUP)  | 
728  | 4.70k  |         { | 
729  | 4.70k  |             continue;  | 
730  | 4.70k  |         }  | 
731  |  |  | 
732  | 83.1k  |         OGRFieldType eType = OFTString;  | 
733  | 83.1k  |         OGRFieldSubType eSubType = OFSTNone;  | 
734  | 83.1k  |         CPLString osOGRFieldName(oField.GetName());  | 
735  | 83.1k  |         switch (oField.GetType())  | 
736  | 83.1k  |         { | 
737  | 45.4k  |             case GMLAS_FT_STRING:  | 
738  | 45.4k  |                 eType = OFTString;  | 
739  | 45.4k  |                 break;  | 
740  | 4.32k  |             case GMLAS_FT_ID:  | 
741  | 4.32k  |             { | 
742  | 4.32k  |                 eType = OFTString;  | 
743  | 4.32k  |                 if (oField.IsNotNullable())  | 
744  | 3.70k  |                 { | 
745  | 3.70k  |                     continue;  | 
746  | 3.70k  |                 }  | 
747  | 620  |                 break;  | 
748  | 4.32k  |             }  | 
749  | 620  |             case GMLAS_FT_BOOLEAN:  | 
750  | 0  |                 eType = OFTInteger;  | 
751  | 0  |                 eSubType = OFSTBoolean;  | 
752  | 0  |                 break;  | 
753  | 0  |             case GMLAS_FT_SHORT:  | 
754  | 0  |                 eType = OFTInteger;  | 
755  | 0  |                 eSubType = OFSTInt16;  | 
756  | 0  |                 break;  | 
757  | 0  |             case GMLAS_FT_INT32:  | 
758  | 0  |                 eType = OFTInteger;  | 
759  | 0  |                 break;  | 
760  | 0  |             case GMLAS_FT_INT64:  | 
761  | 0  |                 eType = OFTInteger64;  | 
762  | 0  |                 break;  | 
763  | 0  |             case GMLAS_FT_FLOAT:  | 
764  | 0  |                 eType = OFTReal;  | 
765  | 0  |                 eSubType = OFSTFloat32;  | 
766  | 0  |                 break;  | 
767  | 0  |             case GMLAS_FT_DOUBLE:  | 
768  | 0  |                 eType = OFTReal;  | 
769  | 0  |                 break;  | 
770  | 0  |             case GMLAS_FT_DECIMAL:  | 
771  | 0  |                 eType = OFTReal;  | 
772  | 0  |                 break;  | 
773  | 0  |             case GMLAS_FT_DATE:  | 
774  | 0  |                 eType = OFTDate;  | 
775  | 0  |                 break;  | 
776  | 0  |             case GMLAS_FT_GYEAR:  | 
777  | 0  |                 eType = OFTInteger;  | 
778  | 0  |                 break;  | 
779  | 0  |             case GMLAS_FT_GYEAR_MONTH:  | 
780  | 0  |                 eType = OFTDate;  | 
781  | 0  |                 break;  | 
782  | 0  |             case GMLAS_FT_TIME:  | 
783  | 0  |                 eType = OFTTime;  | 
784  | 0  |                 break;  | 
785  | 14  |             case GMLAS_FT_DATETIME:  | 
786  | 14  |                 eType = OFTDateTime;  | 
787  | 14  |                 break;  | 
788  | 0  |             case GMLAS_FT_BASE64BINARY:  | 
789  | 0  |             case GMLAS_FT_HEXBINARY:  | 
790  | 0  |                 eType = OFTBinary;  | 
791  | 0  |                 break;  | 
792  | 0  |             case GMLAS_FT_ANYURI:  | 
793  | 0  |                 eType = OFTString;  | 
794  | 0  |                 break;  | 
795  | 33.3k  |             case GMLAS_FT_ANYTYPE:  | 
796  | 33.3k  |                 eType = OFTString;  | 
797  | 33.3k  |                 break;  | 
798  | 0  |             case GMLAS_FT_ANYSIMPLETYPE:  | 
799  | 0  |                 eType = OFTString;  | 
800  | 0  |                 break;  | 
801  | 0  |             case GMLAS_FT_GEOMETRY:  | 
802  | 0  |             { | 
803  |  |                 // Create a geometry field  | 
804  | 0  |                 OGRGeomFieldDefn oGeomFieldDefn(osOGRFieldName,  | 
805  | 0  |                                                 oField.GetGeomType());  | 
806  | 0  |                 m_poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);  | 
807  |  | 
  | 
808  | 0  |                 const int iOGRGeomIdx =  | 
809  | 0  |                     m_poFeatureDefn->GetGeomFieldCount() - 1;  | 
810  | 0  |                 if (!oField.GetXPath().empty())  | 
811  | 0  |                 { | 
812  | 0  |                     m_oMapFieldXPathToOGRGeomFieldIdx[oField.GetXPath()] =  | 
813  | 0  |                         iOGRGeomIdx;  | 
814  | 0  |                 }  | 
815  | 0  |                 else  | 
816  | 0  |                 { | 
817  | 0  |                     const std::vector<CPLString> &aoXPaths =  | 
818  | 0  |                         oField.GetAlternateXPaths();  | 
819  | 0  |                     for (size_t j = 0; j < aoXPaths.size(); j++)  | 
820  | 0  |                     { | 
821  | 0  |                         m_oMapFieldXPathToOGRGeomFieldIdx[aoXPaths[j]] =  | 
822  | 0  |                             iOGRGeomIdx;  | 
823  | 0  |                     }  | 
824  | 0  |                 }  | 
825  |  | 
  | 
826  | 0  |                 m_oMapOGRGeomFieldIdxtoFCFieldIdx[iOGRGeomIdx] = i;  | 
827  |  |  | 
828  |  |                 // Suffix the regular non-geometry field  | 
829  | 0  |                 osOGRFieldName += szXML_SUFFIX;  | 
830  | 0  |                 eType = OFTString;  | 
831  | 0  |                 break;  | 
832  | 0  |             }  | 
833  | 0  |             default:  | 
834  | 0  |                 CPLError(CE_Warning, CPLE_AppDefined,  | 
835  | 0  |                          "Unhandled type in enum: %d", oField.GetType());  | 
836  | 0  |                 break;  | 
837  | 83.1k  |         }  | 
838  |  |  | 
839  | 79.4k  |         if (oField.GetType() == GMLAS_FT_GEOMETRY && !bIncludeGeometryXML)  | 
840  | 0  |         { | 
841  | 0  |             continue;  | 
842  | 0  |         }  | 
843  |  |  | 
844  | 79.4k  |         if (oField.IsArray())  | 
845  | 3  |         { | 
846  | 3  |             switch (eType)  | 
847  | 3  |             { | 
848  | 3  |                 case OFTString:  | 
849  | 3  |                     eType = OFTStringList;  | 
850  | 3  |                     break;  | 
851  | 0  |                 case OFTInteger:  | 
852  | 0  |                     eType = OFTIntegerList;  | 
853  | 0  |                     break;  | 
854  | 0  |                 case OFTInteger64:  | 
855  | 0  |                     eType = OFTInteger64List;  | 
856  | 0  |                     break;  | 
857  | 0  |                 case OFTReal:  | 
858  | 0  |                     eType = OFTRealList;  | 
859  | 0  |                     break;  | 
860  | 0  |                 default:  | 
861  | 0  |                     CPLError(CE_Warning, CPLE_AppDefined,  | 
862  | 0  |                              "Unhandled type in enum: %d", eType);  | 
863  | 0  |                     break;  | 
864  | 3  |             }  | 
865  | 3  |         }  | 
866  | 79.4k  |         OGRFieldDefn oFieldDefn(osOGRFieldName, eType);  | 
867  | 79.4k  |         oFieldDefn.SetSubType(eSubType);  | 
868  | 79.4k  |         if (oField.IsNotNullable())  | 
869  | 1.93k  |             oFieldDefn.SetNullable(false);  | 
870  | 79.4k  |         CPLString osDefaultOrFixed = oField.GetDefaultValue();  | 
871  | 79.4k  |         if (osDefaultOrFixed.empty())  | 
872  | 79.4k  |             osDefaultOrFixed = oField.GetFixedValue();  | 
873  | 79.4k  |         if (!osDefaultOrFixed.empty())  | 
874  | 1  |         { | 
875  | 1  |             char *pszEscaped = CPLEscapeString(osDefaultOrFixed, -1, CPLES_SQL);  | 
876  | 1  |             oFieldDefn.SetDefault(  | 
877  | 1  |                 (CPLString("'") + pszEscaped + CPLString("'")).c_str()); | 
878  | 1  |             CPLFree(pszEscaped);  | 
879  | 1  |         }  | 
880  | 79.4k  |         oFieldDefn.SetWidth(oField.GetWidth());  | 
881  | 79.4k  |         m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
882  |  |  | 
883  | 79.4k  |         const int iOGRIdx = m_poFeatureDefn->GetFieldCount() - 1;  | 
884  | 79.4k  |         if (!oField.GetXPath().empty())  | 
885  | 79.4k  |         { | 
886  | 79.4k  |             m_oMapFieldXPathToOGRFieldIdx[oField.GetXPath()] = iOGRIdx;  | 
887  | 79.4k  |         }  | 
888  | 0  |         else  | 
889  | 0  |         { | 
890  | 0  |             const std::vector<CPLString> &aoXPaths =  | 
891  | 0  |                 oField.GetAlternateXPaths();  | 
892  | 0  |             for (size_t j = 0; j < aoXPaths.size(); j++)  | 
893  | 0  |             { | 
894  | 0  |                 m_oMapFieldXPathToOGRFieldIdx[aoXPaths[j]] = iOGRIdx;  | 
895  | 0  |             }  | 
896  | 0  |         }  | 
897  |  |  | 
898  | 79.4k  |         m_oMapOGRFieldIdxtoFCFieldIdx[iOGRIdx] = i;  | 
899  |  |  | 
900  |  |         // Create field to receive resolved xlink:href content, if needed  | 
901  | 79.4k  |         if (oField.GetXPath().find(szAT_XLINK_HREF) != std::string::npos &&  | 
902  | 79.4k  |             m_poDS->GetConf().m_oXLinkResolution.m_bDefaultResolutionEnabled &&  | 
903  | 79.4k  |             m_poDS->GetConf().m_oXLinkResolution.m_eDefaultResolutionMode ==  | 
904  | 0  |                 GMLASXLinkResolutionConf::RawContent)  | 
905  | 0  |         { | 
906  | 0  |             CPLString osRawContentFieldname(osOGRFieldName);  | 
907  | 0  |             size_t nPos = osRawContentFieldname.find(szHREF_SUFFIX);  | 
908  | 0  |             if (nPos != std::string::npos)  | 
909  | 0  |                 osRawContentFieldname.resize(nPos);  | 
910  | 0  |             osRawContentFieldname += szRAW_CONTENT_SUFFIX;  | 
911  | 0  |             OGRFieldDefn oFieldDefnRaw(osRawContentFieldname, OFTString);  | 
912  | 0  |             m_poFeatureDefn->AddFieldDefn(&oFieldDefnRaw);  | 
913  |  | 
  | 
914  | 0  |             m_oMapFieldXPathToOGRFieldIdx  | 
915  | 0  |                 [GMLASField::MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(  | 
916  | 0  |                     oField.GetXPath())] = m_poFeatureDefn->GetFieldCount() - 1;  | 
917  | 0  |         }  | 
918  |  |  | 
919  | 79.4k  |         CPL_IGNORE_RET_VAL(osOGRFieldName);  | 
920  | 79.4k  |     }  | 
921  |  |  | 
922  | 4.87k  |     CreateCompoundFoldedMappings();  | 
923  | 4.87k  | }  | 
924  |  |  | 
925  |  | /************************************************************************/  | 
926  |  | /*                   CreateCompoundFoldedMappings()                     */  | 
927  |  | /************************************************************************/  | 
928  |  |  | 
929  |  | // In the case we have nested elements but we managed to fold into top  | 
930  |  | // level class, then register intermediate paths so they are not reported  | 
931  |  | // as unexpected in debug traces  | 
932  |  | void OGRGMLASLayer::CreateCompoundFoldedMappings()  | 
933  | 4.87k  | { | 
934  | 4.87k  |     CPLString oFCXPath(m_oFC.GetXPath());  | 
935  | 4.87k  |     if (m_oFC.IsRepeatedSequence())  | 
936  | 0  |     { | 
937  | 0  |         size_t iPosExtra = oFCXPath.find(szEXTRA_SUFFIX);  | 
938  | 0  |         if (iPosExtra != std::string::npos)  | 
939  | 0  |         { | 
940  | 0  |             oFCXPath.resize(iPosExtra);  | 
941  | 0  |         }  | 
942  | 0  |     }  | 
943  |  |  | 
944  | 4.87k  |     const std::vector<GMLASField> &oFields = m_oFC.GetFields();  | 
945  | 92.7k  |     for (size_t i = 0; i < oFields.size(); i++)  | 
946  | 87.8k  |     { | 
947  | 87.8k  |         std::vector<CPLString> aoXPaths = oFields[i].GetAlternateXPaths();  | 
948  | 87.8k  |         if (aoXPaths.empty())  | 
949  | 87.8k  |             aoXPaths.push_back(oFields[i].GetXPath());  | 
950  | 175k  |         for (size_t j = 0; j < aoXPaths.size(); j++)  | 
951  | 87.8k  |         { | 
952  | 87.8k  |             if (aoXPaths[j].size() > oFCXPath.size())  | 
953  | 85.9k  |             { | 
954  |  |                 // Split on both '/' and '@'  | 
955  | 85.9k  |                 char **papszTokens = CSLTokenizeString2(  | 
956  | 85.9k  |                     aoXPaths[j].c_str() + oFCXPath.size() + 1, "/@", 0);  | 
957  | 85.9k  |                 CPLString osSubXPath = oFCXPath;  | 
958  | 85.9k  |                 for (int k = 0;  | 
959  | 238k  |                      papszTokens[k] != nullptr && papszTokens[k + 1] != nullptr;  | 
960  | 152k  |                      k++)  | 
961  | 152k  |                 { | 
962  | 152k  |                     osSubXPath += "/";  | 
963  | 152k  |                     osSubXPath += papszTokens[k];  | 
964  | 152k  |                     if (m_oMapFieldXPathToOGRFieldIdx.find(osSubXPath) ==  | 
965  | 152k  |                         m_oMapFieldXPathToOGRFieldIdx.end())  | 
966  | 313  |                     { | 
967  | 313  |                         m_oMapFieldXPathToOGRFieldIdx[osSubXPath] =  | 
968  | 313  |                             IDX_COMPOUND_FOLDED;  | 
969  | 313  |                     }  | 
970  | 152k  |                 }  | 
971  | 85.9k  |                 CSLDestroy(papszTokens);  | 
972  | 85.9k  |             }  | 
973  | 87.8k  |         }  | 
974  | 87.8k  |     }  | 
975  | 4.87k  | }  | 
976  |  |  | 
977  |  | /************************************************************************/  | 
978  |  | /*                           ~OGRGMLASLayer()                           */  | 
979  |  | /************************************************************************/  | 
980  |  |  | 
981  |  | OGRGMLASLayer::~OGRGMLASLayer()  | 
982  | 9.68k  | { | 
983  | 9.68k  |     m_poFeatureDefn->Release();  | 
984  | 9.68k  | }  | 
985  |  |  | 
986  |  | /************************************************************************/  | 
987  |  | /*                        DeleteTargetIndex()                           */  | 
988  |  | /************************************************************************/  | 
989  |  |  | 
990  |  | static void DeleteTargetIndex(std::map<CPLString, int> &oMap, int nIdx)  | 
991  | 0  | { | 
992  | 0  |     bool bIterToRemoveValid = false;  | 
993  | 0  |     std::map<CPLString, int>::iterator oIterToRemove;  | 
994  | 0  |     std::map<CPLString, int>::iterator oIter = oMap.begin();  | 
995  | 0  |     for (; oIter != oMap.end(); ++oIter)  | 
996  | 0  |     { | 
997  | 0  |         if (oIter->second > nIdx)  | 
998  | 0  |             oIter->second--;  | 
999  | 0  |         else if (oIter->second == nIdx)  | 
1000  | 0  |         { | 
1001  | 0  |             bIterToRemoveValid = true;  | 
1002  | 0  |             oIterToRemove = oIter;  | 
1003  | 0  |         }  | 
1004  | 0  |     }  | 
1005  | 0  |     if (bIterToRemoveValid)  | 
1006  | 0  |         oMap.erase(oIterToRemove);  | 
1007  | 0  | }  | 
1008  |  |  | 
1009  |  | /************************************************************************/  | 
1010  |  | /*                            RemoveField()                             */  | 
1011  |  | /************************************************************************/  | 
1012  |  |  | 
1013  |  | bool OGRGMLASLayer::RemoveField(int nIdx)  | 
1014  | 0  | { | 
1015  | 0  |     if (nIdx == m_nIDFieldIdx || nIdx == m_nParentIDFieldIdx)  | 
1016  | 0  |         return false;  | 
1017  |  |  | 
1018  | 0  |     m_poFeatureDefn->DeleteFieldDefn(nIdx);  | 
1019  |  |  | 
1020  |  |     // Refresh maps  | 
1021  | 0  |     DeleteTargetIndex(m_oMapFieldXPathToOGRFieldIdx, nIdx);  | 
1022  |  | 
  | 
1023  | 0  |     { | 
1024  | 0  |         std::map<int, int> oMapOGRFieldIdxtoFCFieldIdx;  | 
1025  | 0  |         for (const auto &oIter : m_oMapOGRFieldIdxtoFCFieldIdx)  | 
1026  | 0  |         { | 
1027  | 0  |             if (oIter.first < nIdx)  | 
1028  | 0  |                 oMapOGRFieldIdxtoFCFieldIdx[oIter.first] = oIter.second;  | 
1029  | 0  |             else if (oIter.first > nIdx)  | 
1030  | 0  |                 oMapOGRFieldIdxtoFCFieldIdx[oIter.first - 1] = oIter.second;  | 
1031  | 0  |         }  | 
1032  | 0  |         m_oMapOGRFieldIdxtoFCFieldIdx = std::move(oMapOGRFieldIdxtoFCFieldIdx);  | 
1033  | 0  |     }  | 
1034  |  | 
  | 
1035  | 0  |     OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();  | 
1036  | 0  |     OGRFeature *poFeature;  | 
1037  | 0  |     poFieldsMetadataLayer->ResetReading();  | 
1038  | 0  |     while ((poFeature = poFieldsMetadataLayer->GetNextFeature()) != nullptr)  | 
1039  | 0  |     { | 
1040  | 0  |         if (strcmp(poFeature->GetFieldAsString(szLAYER_NAME), GetName()) == 0 &&  | 
1041  | 0  |             poFeature->GetFieldAsInteger(szFIELD_INDEX) == nIdx)  | 
1042  | 0  |         { | 
1043  | 0  |             poFeature->SetField(szFIELD_INDEX, -1);  | 
1044  | 0  |             CPL_IGNORE_RET_VAL(poFieldsMetadataLayer->SetFeature(poFeature));  | 
1045  | 0  |             delete poFeature;  | 
1046  | 0  |             break;  | 
1047  | 0  |         }  | 
1048  | 0  |         delete poFeature;  | 
1049  | 0  |     }  | 
1050  | 0  |     poFieldsMetadataLayer->ResetReading();  | 
1051  |  | 
  | 
1052  | 0  |     return true;  | 
1053  | 0  | }  | 
1054  |  |  | 
1055  |  | /************************************************************************/  | 
1056  |  | /*                        InsertTargetIndex()                           */  | 
1057  |  | /************************************************************************/  | 
1058  |  |  | 
1059  |  | static void InsertTargetIndex(std::map<CPLString, int> &oMap, int nIdx)  | 
1060  | 0  | { | 
1061  | 0  |     for (auto &oIter : oMap)  | 
1062  | 0  |     { | 
1063  | 0  |         if (oIter.second >= nIdx)  | 
1064  | 0  |             oIter.second++;  | 
1065  | 0  |     }  | 
1066  | 0  | }  | 
1067  |  |  | 
1068  |  | /************************************************************************/  | 
1069  |  | /*                            InsertNewField()                          */  | 
1070  |  | /************************************************************************/  | 
1071  |  |  | 
1072  |  | void OGRGMLASLayer::InsertNewField(int nInsertPos,  | 
1073  |  |                                    const OGRFieldDefn &oFieldDefn,  | 
1074  |  |                                    const CPLString &osXPath)  | 
1075  | 0  | { | 
1076  | 0  |     CPLAssert(nInsertPos >= 0 &&  | 
1077  | 0  |               nInsertPos <= m_poFeatureDefn->GetFieldCount());  | 
1078  | 0  |     m_poFeatureDefn->AddFieldDefn(&oFieldDefn);  | 
1079  | 0  |     int *panMap = new int[m_poFeatureDefn->GetFieldCount()];  | 
1080  | 0  |     for (int i = 0; i < nInsertPos; ++i)  | 
1081  | 0  |     { | 
1082  | 0  |         panMap[i] = i;  | 
1083  | 0  |     }  | 
1084  | 0  |     panMap[nInsertPos] = m_poFeatureDefn->GetFieldCount() - 1;  | 
1085  | 0  |     for (int i = nInsertPos + 1; i < m_poFeatureDefn->GetFieldCount(); ++i)  | 
1086  | 0  |     { | 
1087  | 0  |         panMap[i] = i - 1;  | 
1088  | 0  |     }  | 
1089  | 0  |     m_poFeatureDefn->ReorderFieldDefns(panMap);  | 
1090  | 0  |     delete[] panMap;  | 
1091  |  |  | 
1092  |  |     // Refresh maps  | 
1093  | 0  |     InsertTargetIndex(m_oMapFieldXPathToOGRFieldIdx, nInsertPos);  | 
1094  | 0  |     m_oMapFieldXPathToOGRFieldIdx[osXPath] = nInsertPos;  | 
1095  |  | 
  | 
1096  | 0  |     { | 
1097  | 0  |         std::map<int, int> oMapOGRFieldIdxtoFCFieldIdx;  | 
1098  | 0  |         for (const auto &oIter : m_oMapOGRFieldIdxtoFCFieldIdx)  | 
1099  | 0  |         { | 
1100  | 0  |             if (oIter.first < nInsertPos)  | 
1101  | 0  |                 oMapOGRFieldIdxtoFCFieldIdx[oIter.first] = oIter.second;  | 
1102  | 0  |             else  | 
1103  | 0  |                 oMapOGRFieldIdxtoFCFieldIdx[oIter.first + 1] = oIter.second;  | 
1104  | 0  |         }  | 
1105  | 0  |         m_oMapOGRFieldIdxtoFCFieldIdx = std::move(oMapOGRFieldIdxtoFCFieldIdx);  | 
1106  | 0  |     }  | 
1107  |  | 
  | 
1108  | 0  |     OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();  | 
1109  | 0  |     OGRFeature *poFeature;  | 
1110  | 0  |     poFieldsMetadataLayer->ResetReading();  | 
1111  | 0  |     while ((poFeature = poFieldsMetadataLayer->GetNextFeature()) != nullptr)  | 
1112  | 0  |     { | 
1113  | 0  |         if (strcmp(poFeature->GetFieldAsString(szLAYER_NAME), GetName()) == 0)  | 
1114  | 0  |         { | 
1115  | 0  |             int nFieldIndex = poFeature->GetFieldAsInteger(szFIELD_INDEX);  | 
1116  | 0  |             if (nFieldIndex >= nInsertPos && nFieldIndex < INT_MAX)  | 
1117  | 0  |             { | 
1118  | 0  |                 poFeature->SetField(szFIELD_INDEX, nFieldIndex + 1);  | 
1119  | 0  |                 CPL_IGNORE_RET_VAL(  | 
1120  | 0  |                     poFieldsMetadataLayer->SetFeature(poFeature));  | 
1121  | 0  |             }  | 
1122  | 0  |         }  | 
1123  | 0  |         delete poFeature;  | 
1124  | 0  |     }  | 
1125  | 0  |     poFieldsMetadataLayer->ResetReading();  | 
1126  | 0  | }  | 
1127  |  |  | 
1128  |  | /************************************************************************/  | 
1129  |  | /*                       GetOGRFieldIndexFromXPath()                    */  | 
1130  |  | /************************************************************************/  | 
1131  |  |  | 
1132  |  | int OGRGMLASLayer::GetOGRFieldIndexFromXPath(const CPLString &osXPath) const  | 
1133  | 279k  | { | 
1134  | 279k  |     const auto oIter = m_oMapFieldXPathToOGRFieldIdx.find(osXPath);  | 
1135  | 279k  |     if (oIter == m_oMapFieldXPathToOGRFieldIdx.end())  | 
1136  | 270k  |         return -1;  | 
1137  | 9.62k  |     return oIter->second;  | 
1138  | 279k  | }  | 
1139  |  |  | 
1140  |  | /************************************************************************/  | 
1141  |  | /*                       GetXPathFromOGRFieldIndex()                    */  | 
1142  |  | /************************************************************************/  | 
1143  |  |  | 
1144  |  | CPLString OGRGMLASLayer::GetXPathFromOGRFieldIndex(int nIdx) const  | 
1145  | 0  | { | 
1146  | 0  |     const int nFCIdx = GetFCFieldIndexFromOGRFieldIdx(nIdx);  | 
1147  | 0  |     if (nFCIdx >= 0)  | 
1148  | 0  |         return m_oFC.GetFields()[nFCIdx].GetXPath();  | 
1149  |  |  | 
1150  | 0  |     for (const auto &oIter : m_oMapFieldXPathToOGRFieldIdx)  | 
1151  | 0  |     { | 
1152  | 0  |         if (oIter.second == nIdx)  | 
1153  | 0  |             return oIter.first;  | 
1154  | 0  |     }  | 
1155  | 0  |     return CPLString();  | 
1156  | 0  | }  | 
1157  |  |  | 
1158  |  | /************************************************************************/  | 
1159  |  | /*                      GetOGRGeomFieldIndexFromXPath()                 */  | 
1160  |  | /************************************************************************/  | 
1161  |  |  | 
1162  |  | int OGRGMLASLayer::GetOGRGeomFieldIndexFromXPath(const CPLString &osXPath) const  | 
1163  | 138k  | { | 
1164  | 138k  |     const auto oIter = m_oMapFieldXPathToOGRGeomFieldIdx.find(osXPath);  | 
1165  | 138k  |     if (oIter == m_oMapFieldXPathToOGRGeomFieldIdx.end())  | 
1166  | 138k  |         return -1;  | 
1167  | 0  |     return oIter->second;  | 
1168  | 138k  | }  | 
1169  |  |  | 
1170  |  | /************************************************************************/  | 
1171  |  | /*                     GetFCFieldIndexFromOGRFieldIdx()                 */  | 
1172  |  | /************************************************************************/  | 
1173  |  |  | 
1174  |  | int OGRGMLASLayer::GetFCFieldIndexFromOGRFieldIdx(int iOGRFieldIdx) const  | 
1175  | 152k  | { | 
1176  | 152k  |     const auto oIter = m_oMapOGRFieldIdxtoFCFieldIdx.find(iOGRFieldIdx);  | 
1177  | 152k  |     if (oIter == m_oMapOGRFieldIdxtoFCFieldIdx.end())  | 
1178  | 68.2k  |         return -1;  | 
1179  | 83.7k  |     return oIter->second;  | 
1180  | 152k  | }  | 
1181  |  |  | 
1182  |  | /************************************************************************/  | 
1183  |  | /*                     GetFCFieldIndexFromXPath()                       */  | 
1184  |  | /************************************************************************/  | 
1185  |  |  | 
1186  |  | int OGRGMLASLayer::GetFCFieldIndexFromXPath(const CPLString &osXPath) const  | 
1187  | 65.4k  | { | 
1188  | 65.4k  |     const auto oIter = m_oMapFieldXPathToFCFieldIdx.find(osXPath);  | 
1189  | 65.4k  |     if (oIter == m_oMapFieldXPathToFCFieldIdx.end())  | 
1190  | 65.4k  |         return -1;  | 
1191  | 0  |     return oIter->second;  | 
1192  | 65.4k  | }  | 
1193  |  |  | 
1194  |  | /************************************************************************/  | 
1195  |  | /*                  GetFCFieldIndexFromOGRGeomFieldIdx()                */  | 
1196  |  | /************************************************************************/  | 
1197  |  |  | 
1198  |  | int OGRGMLASLayer::GetFCFieldIndexFromOGRGeomFieldIdx(  | 
1199  |  |     int iOGRGeomFieldIdx) const  | 
1200  | 0  | { | 
1201  | 0  |     const auto oIter = m_oMapOGRGeomFieldIdxtoFCFieldIdx.find(iOGRGeomFieldIdx);  | 
1202  | 0  |     if (oIter == m_oMapOGRGeomFieldIdxtoFCFieldIdx.end())  | 
1203  | 0  |         return -1;  | 
1204  | 0  |     return oIter->second;  | 
1205  | 0  | }  | 
1206  |  |  | 
1207  |  | /************************************************************************/  | 
1208  |  | /*                 GetXPathOfFieldLinkForAttrToOtherLayer()             */  | 
1209  |  | /************************************************************************/  | 
1210  |  |  | 
1211  |  | CPLString OGRGMLASLayer::GetXPathOfFieldLinkForAttrToOtherLayer(  | 
1212  |  |     const CPLString &osFieldName, const CPLString &osTargetLayerXPath)  | 
1213  | 0  | { | 
1214  | 0  |     const int nOGRFieldIdx = GetLayerDefn()->GetFieldIndex(osFieldName);  | 
1215  | 0  |     CPLAssert(nOGRFieldIdx >= 0);  | 
1216  | 0  |     const int nFCFieldIdx = GetFCFieldIndexFromOGRFieldIdx(nOGRFieldIdx);  | 
1217  | 0  |     CPLAssert(nFCFieldIdx >= 0);  | 
1218  | 0  |     CPLString osXPath(m_oFC.GetFields()[nFCFieldIdx].GetXPath());  | 
1219  | 0  |     size_t nPos = osXPath.find(szAT_XLINK_HREF);  | 
1220  | 0  |     CPLAssert(nPos != std::string::npos);  | 
1221  | 0  |     CPLAssert(nPos + strlen(szAT_XLINK_HREF) == osXPath.size());  | 
1222  | 0  |     CPLString osTargetFieldXPath(osXPath.substr(0, nPos) + osTargetLayerXPath);  | 
1223  | 0  |     return osTargetFieldXPath;  | 
1224  | 0  | }  | 
1225  |  |  | 
1226  |  | /************************************************************************/  | 
1227  |  | /*                           LaunderFieldName()                         */  | 
1228  |  | /************************************************************************/  | 
1229  |  |  | 
1230  |  | CPLString OGRGMLASLayer::LaunderFieldName(const CPLString &osFieldName)  | 
1231  | 0  | { | 
1232  | 0  |     int nCounter = 1;  | 
1233  | 0  |     CPLString osLaunderedName(osFieldName);  | 
1234  | 0  |     while (m_poFeatureDefn->GetFieldIndex(osLaunderedName) >= 0)  | 
1235  | 0  |     { | 
1236  | 0  |         nCounter++;  | 
1237  | 0  |         osLaunderedName = osFieldName + CPLSPrintf("%d", nCounter); | 
1238  | 0  |     }  | 
1239  |  | 
  | 
1240  | 0  |     const int nIdentifierMaxLength = m_poDS->GetConf().m_nIdentifierMaxLength;  | 
1241  | 0  |     if (nIdentifierMaxLength >= MIN_VALUE_OF_MAX_IDENTIFIER_LENGTH &&  | 
1242  | 0  |         osLaunderedName.size() > static_cast<size_t>(nIdentifierMaxLength))  | 
1243  | 0  |     { | 
1244  | 0  |         osLaunderedName =  | 
1245  | 0  |             OGRGMLASTruncateIdentifier(osLaunderedName, nIdentifierMaxLength);  | 
1246  | 0  |     }  | 
1247  |  | 
  | 
1248  | 0  |     if (m_poDS->GetConf().m_bPGIdentifierLaundering)  | 
1249  | 0  |     { | 
1250  | 0  |         char *pszLaundered =  | 
1251  | 0  |             OGRPGCommonLaunderName(osLaunderedName, "GMLAS", false);  | 
1252  | 0  |         osLaunderedName = pszLaundered;  | 
1253  | 0  |         CPLFree(pszLaundered);  | 
1254  | 0  |     }  | 
1255  |  | 
  | 
1256  | 0  |     if (m_poFeatureDefn->GetFieldIndex(osLaunderedName) >= 0)  | 
1257  | 0  |     { | 
1258  | 0  |         nCounter = 1;  | 
1259  | 0  |         std::string osCandidate;  | 
1260  | 0  |         do  | 
1261  | 0  |         { | 
1262  | 0  |             nCounter++;  | 
1263  | 0  |             osCandidate = OGRGMLASAddSerialNumber(  | 
1264  | 0  |                 osLaunderedName, nCounter, nCounter + 1, nIdentifierMaxLength);  | 
1265  | 0  |         } while (nCounter < 100 &&  | 
1266  | 0  |                  m_poFeatureDefn->GetFieldIndex(osCandidate.c_str()) >= 0);  | 
1267  | 0  |         osLaunderedName = std::move(osCandidate);  | 
1268  | 0  |     }  | 
1269  |  | 
  | 
1270  | 0  |     return osLaunderedName;  | 
1271  | 0  | }  | 
1272  |  |  | 
1273  |  | /************************************************************************/  | 
1274  |  | /*                     CreateLinkForAttrToOtherLayer()                  */  | 
1275  |  | /************************************************************************/  | 
1276  |  |  | 
1277  |  | /* Create a new field to contain the PKID of the feature pointed by this */  | 
1278  |  | /* osFieldName (a xlink:href attribute), when it is an internal link to */  | 
1279  |  | /* another layer whose xpath is given by osTargetLayerXPath */  | 
1280  |  |  | 
1281  |  | CPLString OGRGMLASLayer::CreateLinkForAttrToOtherLayer(  | 
1282  |  |     const CPLString &osFieldName, const CPLString &osTargetLayerXPath)  | 
1283  | 0  | { | 
1284  | 0  |     CPLString osTargetFieldXPath =  | 
1285  | 0  |         GetXPathOfFieldLinkForAttrToOtherLayer(osFieldName, osTargetLayerXPath);  | 
1286  | 0  |     const int nExistingTgtOGRFieldIdx =  | 
1287  | 0  |         GetOGRFieldIndexFromXPath(osTargetFieldXPath);  | 
1288  | 0  |     if (nExistingTgtOGRFieldIdx >= 0)  | 
1289  | 0  |     { | 
1290  | 0  |         return GetLayerDefn()  | 
1291  | 0  |             ->GetFieldDefn(nExistingTgtOGRFieldIdx)  | 
1292  | 0  |             ->GetNameRef();  | 
1293  | 0  |     }  | 
1294  |  |  | 
1295  | 0  |     const int nOGRFieldIdx = GetLayerDefn()->GetFieldIndex(osFieldName);  | 
1296  | 0  |     CPLAssert(nOGRFieldIdx >= 0);  | 
1297  | 0  |     const int nFCFieldIdx = GetFCFieldIndexFromOGRFieldIdx(nOGRFieldIdx);  | 
1298  | 0  |     CPLAssert(nFCFieldIdx >= 0);  | 
1299  | 0  |     CPLString osXPath(m_oFC.GetFields()[nFCFieldIdx].GetXPath());  | 
1300  | 0  |     size_t nPos = osXPath.find(szAT_XLINK_HREF);  | 
1301  | 0  |     CPLString osXPathStart(osXPath.substr(0, nPos));  | 
1302  |  |  | 
1303  |  |     // Find at which position to insert the new field in the layer definition  | 
1304  |  |     // (we could happen at the end, but it will be nicer to insert close to  | 
1305  |  |     // the href field)  | 
1306  | 0  |     int nInsertPos = -1;  | 
1307  | 0  |     for (int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++)  | 
1308  | 0  |     { | 
1309  | 0  |         if (GetXPathFromOGRFieldIndex(i).find(osXPathStart) == 0)  | 
1310  | 0  |         { | 
1311  | 0  |             nInsertPos = i + 1;  | 
1312  | 0  |         }  | 
1313  | 0  |         else if (nInsertPos >= 0)  | 
1314  | 0  |             break;  | 
1315  | 0  |     }  | 
1316  |  | 
  | 
1317  | 0  |     CPLString osNewFieldName(osFieldName);  | 
1318  | 0  |     nPos = osFieldName.find(szHREF_SUFFIX);  | 
1319  | 0  |     if (nPos != std::string::npos)  | 
1320  | 0  |     { | 
1321  | 0  |         osNewFieldName.resize(nPos);  | 
1322  | 0  |     }  | 
1323  | 0  |     osNewFieldName += "_";  | 
1324  | 0  |     OGRGMLASLayer *poTargetLayer = m_poDS->GetLayerByXPath(osTargetLayerXPath);  | 
1325  | 0  |     CPLAssert(poTargetLayer);  | 
1326  | 0  |     osNewFieldName += poTargetLayer->GetName();  | 
1327  | 0  |     osNewFieldName += "_pkid";  | 
1328  | 0  |     osNewFieldName = LaunderFieldName(osNewFieldName);  | 
1329  | 0  |     OGRFieldDefn oFieldDefn(osNewFieldName, OFTString);  | 
1330  | 0  |     InsertNewField(nInsertPos, oFieldDefn, osTargetFieldXPath);  | 
1331  |  | 
  | 
1332  | 0  |     OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();  | 
1333  | 0  |     OGRLayer *poRelationshipsLayer = m_poDS->GetRelationshipsLayer();  | 
1334  |  |  | 
1335  |  |     // Find a relevant location of the field metadata layer into which to  | 
1336  |  |     // insert the new feature (same as above, we could potentially insert just  | 
1337  |  |     // at the end)  | 
1338  | 0  |     GIntBig nFieldsMetadataIdxPos = -1;  | 
1339  | 0  |     poFieldsMetadataLayer->ResetReading();  | 
1340  | 0  |     OGRFeature *poFeature;  | 
1341  | 0  |     while ((poFeature = poFieldsMetadataLayer->GetNextFeature()) != nullptr)  | 
1342  | 0  |     { | 
1343  | 0  |         if (strcmp(poFeature->GetFieldAsString(szLAYER_NAME), GetName()) == 0)  | 
1344  | 0  |         { | 
1345  | 0  |             if (poFeature->GetFieldAsInteger(szFIELD_INDEX) > nInsertPos)  | 
1346  | 0  |             { | 
1347  | 0  |                 delete poFeature;  | 
1348  | 0  |                 break;  | 
1349  | 0  |             }  | 
1350  | 0  |             nFieldsMetadataIdxPos = poFeature->GetFID() + 1;  | 
1351  | 0  |         }  | 
1352  | 0  |         else if (nFieldsMetadataIdxPos >= 0)  | 
1353  | 0  |         { | 
1354  | 0  |             delete poFeature;  | 
1355  | 0  |             break;  | 
1356  | 0  |         }  | 
1357  | 0  |         delete poFeature;  | 
1358  | 0  |     }  | 
1359  | 0  |     poFieldsMetadataLayer->ResetReading();  | 
1360  |  |  | 
1361  |  |     // Move down all features beyond that insertion point  | 
1362  | 0  |     for (GIntBig nFID = poFieldsMetadataLayer->GetFeatureCount() - 1;  | 
1363  | 0  |          nFID >= nFieldsMetadataIdxPos; nFID--)  | 
1364  | 0  |     { | 
1365  | 0  |         poFeature = poFieldsMetadataLayer->GetFeature(nFID);  | 
1366  | 0  |         if (poFeature)  | 
1367  | 0  |         { | 
1368  | 0  |             poFeature->SetFID(nFID + 1);  | 
1369  | 0  |             CPL_IGNORE_RET_VAL(poFieldsMetadataLayer->SetFeature(poFeature));  | 
1370  | 0  |             delete poFeature;  | 
1371  | 0  |         }  | 
1372  | 0  |     }  | 
1373  | 0  |     if (nFieldsMetadataIdxPos >= 0)  | 
1374  | 0  |     { | 
1375  | 0  |         CPL_IGNORE_RET_VAL(  | 
1376  | 0  |             poFieldsMetadataLayer->DeleteFeature(nFieldsMetadataIdxPos));  | 
1377  | 0  |     }  | 
1378  |  |  | 
1379  |  |     // Register field in _ogr_fields_metadata  | 
1380  | 0  |     OGRFeature *poFieldDescFeature =  | 
1381  | 0  |         new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());  | 
1382  | 0  |     poFieldDescFeature->SetField(szLAYER_NAME, GetName());  | 
1383  | 0  |     poFieldDescFeature->SetField(szFIELD_INDEX, nInsertPos);  | 
1384  | 0  |     poFieldDescFeature->SetField(szFIELD_XPATH, osTargetFieldXPath);  | 
1385  | 0  |     poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());  | 
1386  | 0  |     poFieldDescFeature->SetField(szFIELD_TYPE, szXS_STRING);  | 
1387  | 0  |     poFieldDescFeature->SetField(szFIELD_IS_LIST, 0);  | 
1388  | 0  |     poFieldDescFeature->SetField(szFIELD_MIN_OCCURS, 0);  | 
1389  | 0  |     poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, 1);  | 
1390  | 0  |     poFieldDescFeature->SetField(szFIELD_CATEGORY,  | 
1391  | 0  |                                  szPATH_TO_CHILD_ELEMENT_WITH_LINK);  | 
1392  | 0  |     poFieldDescFeature->SetField(szFIELD_RELATED_LAYER,  | 
1393  | 0  |                                  poTargetLayer->GetName());  | 
1394  | 0  |     if (nFieldsMetadataIdxPos >= 0)  | 
1395  | 0  |         poFieldDescFeature->SetFID(nFieldsMetadataIdxPos);  | 
1396  | 0  |     CPL_IGNORE_RET_VAL(  | 
1397  | 0  |         poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));  | 
1398  | 0  |     delete poFieldDescFeature;  | 
1399  |  |  | 
1400  |  |     // Register relationship in _ogr_layer_relationships  | 
1401  | 0  |     OGRFeature *poRelationshipsFeature =  | 
1402  | 0  |         new OGRFeature(poRelationshipsLayer->GetLayerDefn());  | 
1403  | 0  |     poRelationshipsFeature->SetField(szPARENT_LAYER, GetName());  | 
1404  | 0  |     poRelationshipsFeature->SetField(  | 
1405  | 0  |         szPARENT_PKID,  | 
1406  | 0  |         GetLayerDefn()->GetFieldDefn(GetIDFieldIdx())->GetNameRef());  | 
1407  | 0  |     poRelationshipsFeature->SetField(szPARENT_ELEMENT_NAME, osNewFieldName);  | 
1408  | 0  |     poRelationshipsFeature->SetField(szCHILD_LAYER, poTargetLayer->GetName());  | 
1409  | 0  |     poRelationshipsFeature->SetField(  | 
1410  | 0  |         szCHILD_PKID, poTargetLayer->GetLayerDefn()  | 
1411  | 0  |                           ->GetFieldDefn(poTargetLayer->GetIDFieldIdx())  | 
1412  | 0  |                           ->GetNameRef());  | 
1413  | 0  |     CPL_IGNORE_RET_VAL(  | 
1414  | 0  |         poRelationshipsLayer->CreateFeature(poRelationshipsFeature));  | 
1415  | 0  |     delete poRelationshipsFeature;  | 
1416  |  | 
  | 
1417  | 0  |     return osNewFieldName;  | 
1418  | 0  | }  | 
1419  |  |  | 
1420  |  | /************************************************************************/  | 
1421  |  | /*                              GetLayerDefn()                          */  | 
1422  |  | /************************************************************************/  | 
1423  |  |  | 
1424  |  | OGRFeatureDefn *OGRGMLASLayer::GetLayerDefn()  | 
1425  | 3.75M  | { | 
1426  | 3.75M  |     if (!m_bLayerDefnFinalized && m_poDS->IsLayerInitFinished())  | 
1427  | 99  |     { | 
1428  |  |         // If we haven't yet determined the SRS of geometry columns, do it now  | 
1429  | 99  |         m_bLayerDefnFinalized = true;  | 
1430  | 99  |         if (m_poFeatureDefn->GetGeomFieldCount() > 0 ||  | 
1431  | 99  |             m_poDS->GetConf().m_oXLinkResolution.m_bResolveInternalXLinks ||  | 
1432  | 99  |             !m_poDS->GetConf().m_oXLinkResolution.m_aoURLSpecificRules.empty())  | 
1433  | 0  |         { | 
1434  | 0  |             if (m_poReader == nullptr)  | 
1435  | 0  |             { | 
1436  | 0  |                 InitReader();  | 
1437  |  |                 // Avoid keeping too many file descriptor opened  | 
1438  | 0  |                 if (m_fpGML != nullptr)  | 
1439  | 0  |                     m_poDS->PushUnusedGMLFilePointer(m_fpGML);  | 
1440  | 0  |                 m_poReader.reset();  | 
1441  | 0  |             }  | 
1442  | 0  |         }  | 
1443  | 99  |     }  | 
1444  | 3.75M  |     return m_poFeatureDefn;  | 
1445  | 3.75M  | }  | 
1446  |  |  | 
1447  |  | /************************************************************************/  | 
1448  |  | /*                              ResetReading()                          */  | 
1449  |  | /************************************************************************/  | 
1450  |  |  | 
1451  |  | void OGRGMLASLayer::ResetReading()  | 
1452  | 0  | { | 
1453  | 0  |     m_poReader.reset();  | 
1454  | 0  |     m_bEOF = false;  | 
1455  | 0  | }  | 
1456  |  |  | 
1457  |  | /************************************************************************/  | 
1458  |  | /*                              InitReader()                            */  | 
1459  |  | /************************************************************************/  | 
1460  |  |  | 
1461  |  | bool OGRGMLASLayer::InitReader()  | 
1462  | 1.04k  | { | 
1463  | 1.04k  |     CPLAssert(m_poReader == nullptr);  | 
1464  |  |  | 
1465  | 1.04k  |     m_bLayerDefnFinalized = true;  | 
1466  | 1.04k  |     m_poReader.reset(m_poDS->CreateReader(m_fpGML));  | 
1467  | 1.04k  |     if (m_poReader != nullptr)  | 
1468  | 1.04k  |     { | 
1469  | 1.04k  |         m_poReader->SetLayerOfInterest(this);  | 
1470  | 1.04k  |         return true;  | 
1471  | 1.04k  |     }  | 
1472  | 0  |     return false;  | 
1473  | 1.04k  | }  | 
1474  |  |  | 
1475  |  | /************************************************************************/  | 
1476  |  | /*                          GetNextRawFeature()                         */  | 
1477  |  | /************************************************************************/  | 
1478  |  |  | 
1479  |  | OGRFeature *OGRGMLASLayer::GetNextRawFeature()  | 
1480  | 74.7k  | { | 
1481  | 74.7k  |     if (m_poReader == nullptr && !InitReader())  | 
1482  | 0  |         return nullptr;  | 
1483  |  |  | 
1484  | 74.7k  |     return m_poReader->GetNextFeature();  | 
1485  | 74.7k  | }  | 
1486  |  |  | 
1487  |  | /************************************************************************/  | 
1488  |  | /*                            EvaluateFilter()                          */  | 
1489  |  | /************************************************************************/  | 
1490  |  |  | 
1491  |  | bool OGRGMLASLayer::EvaluateFilter(OGRFeature *poFeature)  | 
1492  | 73.7k  | { | 
1493  | 73.7k  |     return (m_poFilterGeom == nullptr ||  | 
1494  | 73.7k  |             FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&  | 
1495  | 73.7k  |            (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature));  | 
1496  | 73.7k  | }  | 
1497  |  |  | 
1498  |  | /************************************************************************/  | 
1499  |  | /*                            GetNextFeature()                          */  | 
1500  |  | /************************************************************************/  | 
1501  |  |  | 
1502  |  | OGRFeature *OGRGMLASLayer::GetNextFeature()  | 
1503  | 74.7k  | { | 
1504  | 74.7k  |     if (m_bEOF)  | 
1505  | 0  |         return nullptr;  | 
1506  |  |  | 
1507  | 74.7k  |     while (true)  | 
1508  | 74.7k  |     { | 
1509  | 74.7k  |         OGRFeature *poFeature = GetNextRawFeature();  | 
1510  | 74.7k  |         if (poFeature == nullptr)  | 
1511  | 1.00k  |         { | 
1512  |  |             // Avoid keeping too many file descriptor opened  | 
1513  | 1.00k  |             if (m_fpGML != nullptr)  | 
1514  | 1.00k  |                 m_poDS->PushUnusedGMLFilePointer(m_fpGML);  | 
1515  | 1.00k  |             m_poReader.reset();  | 
1516  | 1.00k  |             m_bEOF = true;  | 
1517  | 1.00k  |             return nullptr;  | 
1518  | 1.00k  |         }  | 
1519  |  |  | 
1520  | 73.7k  |         if (EvaluateFilter(poFeature))  | 
1521  | 73.7k  |         { | 
1522  | 73.7k  |             return poFeature;  | 
1523  | 73.7k  |         }  | 
1524  |  |  | 
1525  | 0  |         delete poFeature;  | 
1526  | 0  |     }  | 
1527  | 74.7k  | }  |