1 : /******************************************************************************
2 : * $Id: ogrgeorsslayer.cpp 23001 2011-08-28 17:33:04Z rouault $
3 : *
4 : * Project: GeoRSS Translator
5 : * Purpose: Implements OGRGeoRSSLayer class.
6 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2008, Even Rouault
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_georss.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_minixml.h"
33 : #include "ogr_api.h"
34 : #include "ogr_p.h"
35 :
36 : CPL_CVSID("$Id: ogrgeorsslayer.cpp 23001 2011-08-28 17:33:04Z rouault $");
37 :
38 : static const char* apszAllowedATOMFieldNamesWithSubElements[] = { "author", "contributor", NULL };
39 :
40 : static
41 : const char* apszAllowedRSSFieldNames[] = { "title", "link", "description", "author",
42 : "category", "category_domain",
43 : "comments",
44 : "enclosure_url", "enclosure_length", "enclosure_type",
45 : "guid", "guid_isPermaLink",
46 : "pubDate",
47 : "source", "source_url", NULL};
48 :
49 : static
50 : const char* apszAllowedATOMFieldNames[] = { "category_term", "category_scheme", "category_label",
51 : "content", "content_type", "content_xml_lang", "content_xml_base",
52 : "summary", "summary_type", "summary_xml_lang", "summary_xml_base",
53 : "author_name", "author_uri", "author_email",
54 : "contributor_name", "contributor_uri", "contributor_email",
55 : "link_href", "link_rel", "link_type", "link_length",
56 : "id", "published", "rights", "source",
57 : "title", "updated", NULL };
58 :
59 : #define IS_LAT_ELEMENT(pszName) (strncmp(pszName, "geo:lat", strlen("geo:lat")) == 0 || \
60 : strncmp(pszName, "icbm:lat", strlen("icbm:lat")) == 0 || \
61 : strncmp(pszName, "geourl:lat", strlen("geourl:lat")) == 0)
62 :
63 : #define IS_LON_ELEMENT(pszName) (strncmp(pszName, "geo:lon", strlen("geo:lon")) == 0 || \
64 : strncmp(pszName, "icbm:lon", strlen("icbm:lon")) == 0 || \
65 : strncmp(pszName, "geourl:lon", strlen("geourl:lon")) == 0)
66 :
67 : #define IS_GEO_ELEMENT(pszName) (strcmp(pszName, "georss:point") == 0 || \
68 : strcmp(pszName, "georss:line") == 0 || \
69 : strcmp(pszName, "georss:box") == 0 || \
70 : strcmp(pszName, "georss:polygon") == 0 || \
71 : strcmp(pszName, "georss:where") == 0 || \
72 : strncmp(pszName, "gml:", strlen("gml:")) == 0 || \
73 : strncmp(pszName, "geo:", strlen("geo:")) == 0 || \
74 : strncmp(pszName, "icbm:", strlen("icbm:")) == 0 || \
75 : strncmp(pszName, "geourl:", strlen("geourl:")) == 0)
76 :
77 : /************************************************************************/
78 : /* OGRGeoRSSLayer() */
79 : /************************************************************************/
80 :
81 19 : OGRGeoRSSLayer::OGRGeoRSSLayer( const char* pszFilename,
82 : const char* pszLayerName,
83 : OGRGeoRSSDataSource* poDS,
84 : OGRSpatialReference *poSRSIn,
85 19 : int bWriteMode)
86 :
87 : {
88 19 : eof = FALSE;
89 19 : nNextFID = 0;
90 :
91 19 : this->poDS = poDS;
92 19 : this->bWriteMode = bWriteMode;
93 :
94 19 : eFormat = poDS->GetFormat();
95 :
96 19 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
97 19 : poFeatureDefn->Reference();
98 :
99 19 : poSRS = poSRSIn;
100 19 : if (poSRS)
101 1 : poSRS->Reference();
102 :
103 19 : nTotalFeatureCount = 0;
104 :
105 19 : ppoFeatureTab = NULL;
106 19 : nFeatureTabIndex = 0;
107 19 : nFeatureTabLength = 0;
108 19 : pszSubElementName = NULL;
109 19 : pszSubElementValue = NULL;
110 19 : nSubElementValueLen = 0;
111 19 : pszGMLSRSName = NULL;
112 19 : pszTagWithSubTag = NULL;
113 19 : bStopParsing = FALSE;
114 19 : bHasReadSchema = FALSE;
115 19 : setOfFoundFields = NULL;
116 19 : poGlobalGeom = NULL;
117 19 : hasFoundLat = FALSE;
118 19 : hasFoundLon = FALSE;
119 :
120 19 : poFeature = NULL;
121 :
122 : #ifdef HAVE_EXPAT
123 19 : oParser = NULL;
124 : #endif
125 :
126 19 : if (bWriteMode == FALSE)
127 : {
128 13 : fpGeoRSS = VSIFOpenL( pszFilename, "r" );
129 13 : if( fpGeoRSS == NULL )
130 : {
131 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszFilename);
132 0 : return;
133 : }
134 : }
135 : else
136 6 : fpGeoRSS = NULL;
137 :
138 19 : ResetReading();
139 0 : }
140 :
141 : /************************************************************************/
142 : /* ~OGRGeoRSSLayer() */
143 : /************************************************************************/
144 :
145 19 : OGRGeoRSSLayer::~OGRGeoRSSLayer()
146 :
147 : {
148 : #ifdef HAVE_EXPAT
149 19 : if (oParser)
150 13 : XML_ParserFree(oParser);
151 : #endif
152 19 : poFeatureDefn->Release();
153 :
154 19 : if( poSRS != NULL )
155 10 : poSRS->Release();
156 :
157 19 : CPLFree(pszSubElementName);
158 19 : CPLFree(pszSubElementValue);
159 19 : CPLFree(pszGMLSRSName);
160 19 : CPLFree(pszTagWithSubTag);
161 19 : if (setOfFoundFields)
162 12 : CPLHashSetDestroy(setOfFoundFields);
163 19 : if (poGlobalGeom)
164 0 : delete poGlobalGeom;
165 :
166 : int i;
167 19 : for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
168 0 : delete ppoFeatureTab[i];
169 19 : CPLFree(ppoFeatureTab);
170 :
171 19 : if (poFeature)
172 0 : delete poFeature;
173 :
174 19 : if (fpGeoRSS)
175 13 : VSIFCloseL( fpGeoRSS );
176 19 : }
177 :
178 :
179 : /************************************************************************/
180 : /* GetLayerDefn() */
181 : /************************************************************************/
182 :
183 17 : OGRFeatureDefn * OGRGeoRSSLayer::GetLayerDefn()
184 : {
185 17 : if (!bHasReadSchema)
186 8 : LoadSchema();
187 :
188 17 : return poFeatureDefn;
189 : }
190 :
191 :
192 :
193 : #ifdef HAVE_EXPAT
194 :
195 276 : static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
196 : const char **ppszAttr)
197 : {
198 276 : ((OGRGeoRSSLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
199 276 : }
200 :
201 276 : static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
202 : {
203 276 : ((OGRGeoRSSLayer*)pUserData)->endElementCbk(pszName);
204 276 : }
205 :
206 792 : static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
207 : {
208 792 : ((OGRGeoRSSLayer*)pUserData)->dataHandlerCbk(data, nLen);
209 792 : }
210 :
211 : #endif
212 :
213 : /************************************************************************/
214 : /* ResetReading() */
215 : /************************************************************************/
216 :
217 19 : void OGRGeoRSSLayer::ResetReading()
218 :
219 : {
220 19 : if (bWriteMode)
221 6 : return;
222 :
223 13 : eof = FALSE;
224 13 : nNextFID = 0;
225 13 : if (fpGeoRSS)
226 : {
227 13 : VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
228 : #ifdef HAVE_EXPAT
229 13 : if (oParser)
230 0 : XML_ParserFree(oParser);
231 :
232 13 : oParser = OGRCreateExpatXMLParser();
233 13 : XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
234 13 : XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
235 13 : XML_SetUserData(oParser, this);
236 : #endif
237 : }
238 13 : bInFeature = FALSE;
239 13 : hasFoundLat = FALSE;
240 13 : hasFoundLon = FALSE;
241 13 : bInSimpleGeometry = FALSE;
242 13 : bInGMLGeometry = FALSE;
243 13 : bInGeoLat = FALSE;
244 13 : bInGeoLong = FALSE;
245 13 : eGeomType = wkbUnknown;
246 13 : CPLFree(pszSubElementName);
247 13 : pszSubElementName = NULL;
248 13 : CPLFree(pszSubElementValue);
249 13 : pszSubElementValue = NULL;
250 13 : nSubElementValueLen = 0;
251 13 : CPLFree(pszGMLSRSName);
252 13 : pszGMLSRSName = NULL;
253 :
254 13 : if (setOfFoundFields)
255 0 : CPLHashSetDestroy(setOfFoundFields);
256 13 : setOfFoundFields = NULL;
257 :
258 : int i;
259 13 : for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
260 0 : delete ppoFeatureTab[i];
261 13 : CPLFree(ppoFeatureTab);
262 13 : nFeatureTabIndex = 0;
263 13 : nFeatureTabLength = 0;
264 13 : ppoFeatureTab = NULL;
265 13 : if (poFeature)
266 0 : delete poFeature;
267 13 : poFeature = NULL;
268 :
269 13 : currentDepth = 0;
270 13 : featureDepth = 0;
271 13 : geometryDepth = 0;
272 13 : bInTagWithSubTag = FALSE;
273 13 : CPLFree(pszTagWithSubTag);
274 13 : pszTagWithSubTag = NULL;
275 : }
276 :
277 : #ifdef HAVE_EXPAT
278 :
279 : /************************************************************************/
280 : /* AddStrToSubElementValue() */
281 : /************************************************************************/
282 :
283 188 : void OGRGeoRSSLayer::AddStrToSubElementValue(const char* pszStr)
284 : {
285 188 : int len = strlen(pszStr);
286 : char* pszNewSubElementValue = (char*)
287 188 : VSIRealloc(pszSubElementValue, nSubElementValueLen + len + 1);
288 188 : if (pszNewSubElementValue == NULL)
289 : {
290 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
291 0 : XML_StopParser(oParser, XML_FALSE);
292 0 : bStopParsing = TRUE;
293 0 : return;
294 : }
295 188 : pszSubElementValue = pszNewSubElementValue;
296 :
297 188 : memcpy(pszSubElementValue + nSubElementValueLen, pszStr, len);
298 188 : nSubElementValueLen += len;
299 : }
300 :
301 : /************************************************************************/
302 : /* OGRGeoRSS_GetOGRCompatibleTagName() */
303 : /************************************************************************/
304 :
305 : /** Replace ':' from XML NS element name by '_' more OGR friendly */
306 312 : static char* OGRGeoRSS_GetOGRCompatibleTagName(const char* pszName)
307 : {
308 312 : char* pszModName = CPLStrdup(pszName);
309 : int i;
310 2712 : for(i=0;pszModName[i] != 0;i++)
311 : {
312 2400 : if (pszModName[i] == ':')
313 24 : pszModName[i] = '_';
314 : }
315 312 : return pszModName;
316 : }
317 :
318 : /************************************************************************/
319 : /* OGRGeoRSSLayerATOMTagHasSubElement() */
320 : /************************************************************************/
321 :
322 80 : static int OGRGeoRSSLayerATOMTagHasSubElement(const char* pszName)
323 : {
324 : unsigned int i;
325 208 : for(i=0;apszAllowedATOMFieldNamesWithSubElements[i] != NULL;i++)
326 : {
327 152 : if (strcmp(pszName, apszAllowedATOMFieldNamesWithSubElements[i]) == 0)
328 24 : return TRUE;
329 : }
330 56 : return FALSE;
331 : }
332 :
333 : /************************************************************************/
334 : /* startElementCbk() */
335 : /************************************************************************/
336 :
337 276 : void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
338 : {
339 276 : int bSerializeTag = FALSE;
340 :
341 276 : if (bStopParsing) return;
342 :
343 303 : if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
344 : ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && !bInFeature && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
345 : {
346 27 : featureDepth = currentDepth;
347 :
348 27 : if (poFeature)
349 0 : delete poFeature;
350 :
351 27 : poFeature = new OGRFeature( poFeatureDefn );
352 27 : poFeature->SetFID( nNextFID++ );
353 :
354 27 : bInFeature = TRUE;
355 27 : hasFoundLat = FALSE;
356 27 : hasFoundLon = FALSE;
357 27 : bInSimpleGeometry = FALSE;
358 27 : bInGMLGeometry = FALSE;
359 27 : bInGeoLat = FALSE;
360 27 : bInGeoLong = FALSE;
361 27 : eGeomType = wkbUnknown;
362 27 : geometryDepth = 0;
363 27 : bInTagWithSubTag = FALSE;
364 :
365 27 : if (setOfFoundFields)
366 15 : CPLHashSetDestroy(setOfFoundFields);
367 27 : setOfFoundFields = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
368 : }
369 259 : else if (bInFeature && bInTagWithSubTag && currentDepth == 3)
370 : {
371 10 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszName));
372 :
373 10 : CPLFree(pszSubElementName);
374 10 : pszSubElementName = NULL;
375 10 : CPLFree(pszSubElementValue);
376 10 : pszSubElementValue = NULL;
377 10 : nSubElementValueLen = 0;
378 :
379 10 : iCurrentField = poFeatureDefn->GetFieldIndex(pszFieldName);
380 10 : if (iCurrentField >= 0)
381 10 : pszSubElementName = CPLStrdup(pszFieldName);
382 :
383 10 : CPLFree(pszFieldName);
384 : }
385 239 : else if (bInFeature && eFormat == GEORSS_ATOM &&
386 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
387 : {
388 6 : CPLFree(pszTagWithSubTag);
389 6 : pszTagWithSubTag = CPLStrdup(pszName);
390 :
391 6 : int count = 1;
392 14 : while(CPLHashSetLookup(setOfFoundFields, pszTagWithSubTag) != NULL)
393 : {
394 2 : count ++;
395 2 : CPLFree(pszTagWithSubTag);
396 2 : pszTagWithSubTag = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
397 : }
398 6 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
399 :
400 6 : bInTagWithSubTag = TRUE;
401 : }
402 233 : else if (bInGMLGeometry)
403 : {
404 17 : bSerializeTag = TRUE;
405 : }
406 216 : else if (bInSimpleGeometry || bInGeoLat || bInGeoLong)
407 : {
408 : /* Shouldn't happen for a valid document */
409 : }
410 217 : else if (IS_LAT_ELEMENT(pszName))
411 : {
412 1 : CPLFree(pszSubElementValue);
413 1 : pszSubElementValue = NULL;
414 1 : nSubElementValueLen = 0;
415 1 : bInGeoLat = TRUE;
416 : }
417 216 : else if (IS_LON_ELEMENT(pszName))
418 : {
419 1 : CPLFree(pszSubElementValue);
420 1 : pszSubElementValue = NULL;
421 1 : nSubElementValueLen = 0;
422 1 : bInGeoLong = TRUE;
423 : }
424 224 : else if (strcmp(pszName, "georss:point") == 0 ||
425 : strcmp(pszName, "georss:line") == 0 ||
426 : strcmp(pszName, "geo:line") == 0 ||
427 : strcmp(pszName, "georss:polygon") == 0 ||
428 : strcmp(pszName, "georss:box") == 0)
429 : {
430 10 : CPLFree(pszSubElementValue);
431 10 : pszSubElementValue = NULL;
432 10 : nSubElementValueLen = 0;
433 : eGeomType = strcmp(pszName, "georss:point") == 0 ? wkbPoint :
434 : (strcmp(pszName, "georss:line") == 0 ||
435 : strcmp(pszName, "geo:line") == 0) ? wkbLineString :
436 : (strcmp(pszName, "georss:polygon") == 0 ||
437 : strcmp(pszName, "georss:box") == 0) ? wkbPolygon :
438 10 : wkbUnknown;
439 10 : bInSimpleGeometry = TRUE;
440 10 : geometryDepth = currentDepth;
441 : }
442 214 : else if (strcmp(pszName, "gml:Point") == 0 ||
443 : strcmp(pszName, "gml:LineString") == 0 ||
444 : strcmp(pszName, "gml:Polygon") == 0 ||
445 : strcmp(pszName, "gml:MultiPoint") == 0 ||
446 : strcmp(pszName, "gml:MultiLineString") == 0 ||
447 : strcmp(pszName, "gml:MultiPolygon") == 0 ||
448 : strcmp(pszName, "gml:Envelope") == 0)
449 : {
450 10 : CPLFree(pszSubElementValue);
451 10 : pszSubElementValue = NULL;
452 10 : nSubElementValueLen = 0;
453 10 : AddStrToSubElementValue(CPLSPrintf("<%s>", pszName));
454 10 : bInGMLGeometry = TRUE;
455 10 : geometryDepth = currentDepth;
456 10 : CPLFree(pszGMLSRSName);
457 10 : pszGMLSRSName = NULL;
458 11 : for (int i = 0; ppszAttr[i]; i += 2)
459 : {
460 1 : if (strcmp(ppszAttr[i], "srsName") == 0)
461 : {
462 1 : if (pszGMLSRSName == NULL)
463 1 : pszGMLSRSName = CPLStrdup(ppszAttr[i+1]);
464 : }
465 : }
466 : }
467 324 : else if (bInFeature && currentDepth == featureDepth + 1)
468 : {
469 130 : CPLFree(pszSubElementName);
470 130 : pszSubElementName = NULL;
471 130 : CPLFree(pszSubElementValue);
472 130 : pszSubElementValue = NULL;
473 130 : nSubElementValueLen = 0;
474 130 : iCurrentField = -1;
475 :
476 130 : pszSubElementName = CPLStrdup(pszName);
477 130 : int count = 1;
478 267 : while(CPLHashSetLookup(setOfFoundFields, pszSubElementName) != NULL)
479 : {
480 7 : count ++;
481 7 : CPLFree(pszSubElementName);
482 7 : pszSubElementName = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
483 : }
484 130 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszSubElementName));
485 :
486 130 : char* pszCompatibleName = OGRGeoRSS_GetOGRCompatibleTagName(pszSubElementName);
487 130 : iCurrentField = poFeatureDefn->GetFieldIndex(pszCompatibleName);
488 130 : CPLFree(pszSubElementName);
489 :
490 161 : for(int i = 0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL; i+=2)
491 : {
492 : char* pszAttrCompatibleName =
493 31 : OGRGeoRSS_GetOGRCompatibleTagName(CPLSPrintf("%s_%s", pszCompatibleName, ppszAttr[i]));
494 31 : int iAttrField = poFeatureDefn->GetFieldIndex(pszAttrCompatibleName);
495 31 : if (iAttrField >= 0)
496 : {
497 31 : if (poFeatureDefn->GetFieldDefn(iAttrField)->GetType() == OFTReal)
498 0 : poFeature->SetField( iAttrField, CPLAtof(ppszAttr[i+1]) );
499 : else
500 31 : poFeature->SetField( iAttrField, ppszAttr[i+1] );
501 : }
502 31 : CPLFree(pszAttrCompatibleName);
503 : }
504 :
505 130 : if (iCurrentField < 0)
506 : {
507 14 : pszSubElementName = NULL;
508 : }
509 : else
510 : {
511 116 : pszSubElementName = CPLStrdup(pszCompatibleName);
512 : }
513 130 : CPLFree(pszCompatibleName);
514 : }
515 64 : else if (bInFeature && currentDepth > featureDepth + 1 && pszSubElementName != NULL)
516 : {
517 6 : bSerializeTag = TRUE;
518 : }
519 :
520 276 : if (bSerializeTag)
521 : {
522 23 : AddStrToSubElementValue("<");
523 23 : AddStrToSubElementValue(pszName);
524 25 : for(int i = 0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL; i+=2)
525 : {
526 2 : AddStrToSubElementValue(" ");
527 2 : AddStrToSubElementValue(ppszAttr[i]);
528 2 : AddStrToSubElementValue("=\"");
529 2 : AddStrToSubElementValue(ppszAttr[i+1]);
530 2 : AddStrToSubElementValue("\"");
531 : }
532 23 : AddStrToSubElementValue(">");
533 : }
534 :
535 276 : currentDepth++;
536 : }
537 :
538 : /************************************************************************/
539 : /* OGRGeoRSS_GetGMLEnvelope() */
540 : /************************************************************************/
541 :
542 1 : static OGRGeometry* OGRGeoRSS_GetGMLEnvelope(const char* pszGML)
543 : {
544 1 : OGRGeometry* poGeom = NULL;
545 1 : CPLXMLNode* poNode = CPLParseXMLString(pszGML);
546 1 : const char* pszLowerCorner = CPLGetXMLValue(poNode, "gml:lowerCorner", NULL);
547 1 : const char* pszUpperCorner = CPLGetXMLValue(poNode, "gml:upperCorner", NULL);
548 1 : if (pszLowerCorner && pszUpperCorner)
549 : {
550 : char **papszTokensLower;
551 : char **papszTokensUpper;
552 :
553 : papszTokensLower = CSLTokenizeStringComplex(
554 1 : pszLowerCorner, " ,", FALSE, FALSE );
555 : papszTokensUpper = CSLTokenizeStringComplex(
556 1 : pszUpperCorner, " ,", FALSE, FALSE );
557 1 : if (CSLCount(papszTokensLower) == 2 &&
558 : CSLCount(papszTokensUpper) == 2)
559 : {
560 1 : OGRPolygon* poPolygon = new OGRPolygon();
561 2 : OGRLinearRing* poLinearRing = new OGRLinearRing();
562 1 : poPolygon->addRingDirectly(poLinearRing);
563 1 : double x1 = CPLAtof(papszTokensLower[0]);
564 1 : double y1 = CPLAtof(papszTokensLower[1]);
565 1 : double x2 = CPLAtof(papszTokensUpper[0]);
566 1 : double y2 = CPLAtof(papszTokensUpper[1]);
567 1 : poLinearRing->addPoint( x1, y1 );
568 1 : poLinearRing->addPoint( x2, y1 );
569 1 : poLinearRing->addPoint( x2, y2 );
570 1 : poLinearRing->addPoint( x1, y2 );
571 1 : poLinearRing->addPoint( x1, y1 );
572 :
573 1 : poGeom = poPolygon;
574 : }
575 :
576 1 : CSLDestroy(papszTokensLower);
577 1 : CSLDestroy(papszTokensUpper);
578 : }
579 1 : CPLDestroyXMLNode(poNode);
580 1 : return poGeom;
581 : }
582 :
583 :
584 : /************************************************************************/
585 : /* OGRGeoRSSLayerTrimLeadingAndTrailingSpaces() */
586 : /************************************************************************/
587 :
588 10 : static void OGRGeoRSSLayerTrimLeadingAndTrailingSpaces(char* pszStr)
589 : {
590 : int i;
591 :
592 : /* Trim leading spaces, tabs and newlines */
593 10 : i = 0;
594 62 : while(pszStr[i] != '\0' &&
595 39 : (pszStr[i] == ' ' || pszStr[i] == '\t' || pszStr[i] == '\n'))
596 3 : i ++;
597 10 : memmove(pszStr, pszStr + i, strlen(pszStr + i) + 1);
598 :
599 : /* Trim trailing spaces, tabs and newlines */
600 10 : i = strlen(pszStr) - 1;
601 56 : while(i >= 0 &&
602 33 : (pszStr[i] == ' ' || pszStr[i] == '\t' || pszStr[i] == '\n'))
603 : {
604 3 : pszStr[i] = '\0';
605 3 : i --;
606 : }
607 10 : }
608 :
609 : /************************************************************************/
610 : /* endElementCbk() */
611 : /************************************************************************/
612 :
613 276 : void OGRGeoRSSLayer::endElementCbk(const char *pszName)
614 : {
615 276 : OGRGeometry* poGeom = NULL;
616 :
617 276 : if (bStopParsing) return;
618 :
619 276 : currentDepth--;
620 :
621 276 : if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
622 : ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
623 : {
624 27 : bInFeature = FALSE;
625 27 : bInTagWithSubTag = FALSE;
626 :
627 28 : if (hasFoundLat && hasFoundLon)
628 1 : poFeature->SetGeometryDirectly( new OGRPoint( lonVal, latVal ) );
629 26 : else if (poFeature->GetGeometryRef() == NULL && poGlobalGeom != NULL)
630 0 : poFeature->SetGeometry(poGlobalGeom);
631 :
632 27 : hasFoundLat = FALSE;
633 27 : hasFoundLon = FALSE;
634 :
635 27 : if (poSRS != NULL && poFeature->GetGeometryRef() != NULL)
636 19 : poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
637 :
638 27 : if( (m_poFilterGeom == NULL
639 : || FilterGeometry( poFeature->GetGeometryRef() ) )
640 : && (m_poAttrQuery == NULL
641 : || m_poAttrQuery->Evaluate( poFeature )) )
642 : {
643 : ppoFeatureTab = (OGRFeature**)
644 : CPLRealloc(ppoFeatureTab,
645 27 : sizeof(OGRFeature*) * (nFeatureTabLength + 1));
646 27 : ppoFeatureTab[nFeatureTabLength] = poFeature;
647 27 : nFeatureTabLength++;
648 : }
649 : else
650 : {
651 0 : delete poFeature;
652 : }
653 27 : poFeature = NULL;
654 27 : return;
655 : }
656 :
657 259 : if (bInTagWithSubTag && currentDepth == 3)
658 : {
659 10 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszName));
660 :
661 10 : if (iCurrentField != -1 && pszSubElementName &&
662 : strcmp(pszFieldName, pszSubElementName) == 0 && poFeature &&
663 : pszSubElementValue && nSubElementValueLen)
664 : {
665 10 : pszSubElementValue[nSubElementValueLen] = 0;
666 10 : if (poFeatureDefn->GetFieldDefn(iCurrentField)->GetType() == OFTReal)
667 0 : poFeature->SetField( iCurrentField, CPLAtof(pszSubElementValue) );
668 : else
669 10 : poFeature->SetField( iCurrentField, pszSubElementValue);
670 : }
671 :
672 10 : CPLFree(pszSubElementName);
673 10 : pszSubElementName = NULL;
674 10 : CPLFree(pszSubElementValue);
675 10 : pszSubElementValue = NULL;
676 10 : nSubElementValueLen = 0;
677 :
678 10 : CPLFree(pszFieldName);
679 : }
680 239 : else if (bInFeature && eFormat == GEORSS_ATOM &&
681 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
682 : {
683 6 : bInTagWithSubTag = FALSE;
684 : }
685 233 : else if (bInGMLGeometry)
686 : {
687 27 : AddStrToSubElementValue("</");
688 27 : AddStrToSubElementValue(pszName);
689 27 : AddStrToSubElementValue(">");
690 27 : if (currentDepth > geometryDepth)
691 : {
692 : }
693 : else
694 : {
695 10 : pszSubElementValue[nSubElementValueLen] = 0;
696 10 : CPLAssert(strncmp(pszName, "gml:", 4) == 0);
697 10 : if (strcmp(pszName, "gml:Envelope") == 0)
698 1 : poGeom = OGRGeoRSS_GetGMLEnvelope(pszSubElementValue);
699 : else
700 9 : poGeom = (OGRGeometry*) OGR_G_CreateFromGML(pszSubElementValue);
701 :
702 10 : if (poGeom != NULL && !poGeom->IsEmpty() )
703 : {
704 9 : int bSwapCoordinates = FALSE;
705 9 : if (pszGMLSRSName)
706 : {
707 1 : OGRSpatialReference* poSRSFeature = new OGRSpatialReference();
708 1 : poSRSFeature->importFromURN(pszGMLSRSName);
709 1 : poGeom->assignSpatialReference(poSRSFeature);
710 1 : poSRSFeature->Release();
711 : }
712 : else
713 8 : bSwapCoordinates = TRUE; /* lat, lon WGS 84 */
714 :
715 9 : if (bSwapCoordinates)
716 : {
717 8 : poGeom->swapXY();
718 : }
719 : }
720 10 : bInGMLGeometry = FALSE;
721 : }
722 : }
723 206 : else if (bInSimpleGeometry)
724 : {
725 10 : if (currentDepth > geometryDepth)
726 : {
727 : /* Shouldn't happen for a valid document */
728 : }
729 : else
730 : {
731 10 : if (pszSubElementValue)
732 : {
733 10 : pszSubElementValue[nSubElementValueLen] = 0;
734 :
735 : /* Trim any leading and trailing spaces, tabs, newlines, etc... */
736 10 : OGRGeoRSSLayerTrimLeadingAndTrailingSpaces(pszSubElementValue);
737 :
738 : /* Caution : Order is latitude, longitude */
739 : char** papszTokens =
740 : CSLTokenizeStringComplex( pszSubElementValue,
741 10 : " ,", TRUE, FALSE );
742 :
743 10 : int nTokens = CSLCount(papszTokens);
744 11 : if ((nTokens % 2) != 0 ||
745 : (eGeomType == wkbPoint && nTokens != 2) ||
746 : (eGeomType == wkbLineString && nTokens < 4) ||
747 : (strcmp(pszName, "georss:polygon") == 0 && nTokens < 6) ||
748 : (strcmp(pszName, "georss:box") == 0 && nTokens != 4))
749 : {
750 : CPLError(CE_Failure, CPLE_AppDefined,
751 : "Wrong number of coordinates in %s",
752 1 : pszSubElementValue);
753 : }
754 9 : else if (eGeomType == wkbPoint)
755 : {
756 3 : poGeom = new OGRPoint( CPLAtof(papszTokens[1]),
757 6 : CPLAtof(papszTokens[0]) );
758 : }
759 6 : else if (eGeomType == wkbLineString)
760 : {
761 2 : OGRLineString* poLineString = new OGRLineString ();
762 2 : poGeom = poLineString;
763 : int i;
764 8 : for(i=0;i<nTokens;i+=2)
765 : {
766 6 : poLineString->addPoint( CPLAtof(papszTokens[i+1]),
767 12 : CPLAtof(papszTokens[i]) );
768 : }
769 : }
770 4 : else if (eGeomType == wkbPolygon)
771 : {
772 4 : OGRPolygon* poPolygon = new OGRPolygon();
773 8 : OGRLinearRing* poLinearRing = new OGRLinearRing();
774 4 : poGeom = poPolygon;
775 4 : poPolygon->addRingDirectly(poLinearRing);
776 4 : if (strcmp(pszName, "georss:polygon") == 0)
777 : {
778 : int i;
779 18 : for(i=0;i<nTokens;i+=2)
780 : {
781 15 : poLinearRing->addPoint( CPLAtof(papszTokens[i+1]),
782 30 : CPLAtof(papszTokens[i]) );
783 : }
784 : }
785 : else
786 : {
787 1 : double lat1 = CPLAtof(papszTokens[0]);
788 1 : double lon1 = CPLAtof(papszTokens[1]);
789 1 : double lat2 = CPLAtof(papszTokens[2]);
790 1 : double lon2 = CPLAtof(papszTokens[3]);
791 1 : poLinearRing->addPoint( lon1, lat1 );
792 1 : poLinearRing->addPoint( lon1, lat2 );
793 1 : poLinearRing->addPoint( lon2, lat2 );
794 1 : poLinearRing->addPoint( lon2, lat1 );
795 1 : poLinearRing->addPoint( lon1, lat1 );
796 : }
797 : }
798 :
799 10 : CSLDestroy(papszTokens);
800 : }
801 10 : bInSimpleGeometry = FALSE;
802 : }
803 : }
804 197 : else if (IS_LAT_ELEMENT(pszName))
805 : {
806 1 : if (pszSubElementValue)
807 : {
808 1 : hasFoundLat = TRUE;
809 1 : pszSubElementValue[nSubElementValueLen] = 0;
810 1 : latVal = CPLAtof(pszSubElementValue);
811 : }
812 1 : bInGeoLat = FALSE;
813 : }
814 196 : else if (IS_LON_ELEMENT(pszName))
815 : {
816 1 : if (pszSubElementValue)
817 : {
818 1 : hasFoundLon = TRUE;
819 1 : pszSubElementValue[nSubElementValueLen] = 0;
820 1 : lonVal = CPLAtof(pszSubElementValue);
821 : }
822 1 : bInGeoLong = FALSE;
823 : }
824 324 : else if (bInFeature && currentDepth == featureDepth + 1)
825 : {
826 130 : if (iCurrentField != -1 && pszSubElementName &&
827 : poFeature && pszSubElementValue && nSubElementValueLen)
828 : {
829 116 : pszSubElementValue[nSubElementValueLen] = 0;
830 116 : if (poFeatureDefn->GetFieldDefn(iCurrentField)->GetType() == OFTDateTime)
831 : {
832 : int year, month, day, hour, minute, TZ;
833 : int nsecond;
834 : float fsecond;
835 25 : if (OGRParseRFC822DateTime(pszSubElementValue, &year, &month, &day,
836 : &hour, &minute, &nsecond, &TZ))
837 : {
838 : poFeature->SetField(iCurrentField, year, month, day,
839 21 : hour, minute, nsecond, TZ);
840 : }
841 4 : else if (OGRParseXMLDateTime(pszSubElementValue, &year, &month, &day,
842 : &hour, &minute, &fsecond, &TZ))
843 : {
844 : poFeature->SetField(iCurrentField, year, month, day,
845 4 : hour, minute, (int)(fsecond + .5), TZ);
846 : }
847 : else
848 : {
849 : CPLError(CE_Warning, CPLE_AppDefined,
850 0 : "Could not parse %s as a valid dateTime", pszSubElementValue);
851 : }
852 : }
853 : else
854 : {
855 91 : if (poFeatureDefn->GetFieldDefn(iCurrentField)->GetType() == OFTReal)
856 0 : poFeature->SetField( iCurrentField, CPLAtof(pszSubElementValue) );
857 : else
858 91 : poFeature->SetField( iCurrentField, pszSubElementValue);
859 : }
860 : }
861 :
862 130 : CPLFree(pszSubElementName);
863 130 : pszSubElementName = NULL;
864 130 : CPLFree(pszSubElementValue);
865 130 : pszSubElementValue = NULL;
866 130 : nSubElementValueLen = 0;
867 : }
868 64 : else if (bInFeature && currentDepth > featureDepth + 1 && pszSubElementName != NULL)
869 : {
870 6 : AddStrToSubElementValue("</");
871 6 : AddStrToSubElementValue(pszName);
872 6 : AddStrToSubElementValue(">");
873 : }
874 :
875 249 : if (poGeom != NULL)
876 : {
877 18 : if (poFeature != NULL)
878 : {
879 18 : poFeature->SetGeometryDirectly(poGeom);
880 : }
881 0 : else if (!bInFeature)
882 : {
883 0 : if (poGlobalGeom != NULL)
884 0 : delete poGlobalGeom;
885 0 : poGlobalGeom = poGeom;
886 : }
887 : else
888 0 : delete poGeom;
889 : }
890 231 : else if (!bInFeature && hasFoundLat && hasFoundLon)
891 : {
892 0 : if (poGlobalGeom != NULL)
893 0 : delete poGlobalGeom;
894 0 : poGlobalGeom = new OGRPoint( lonVal, latVal );
895 0 : hasFoundLat = hasFoundLon = FALSE;
896 : }
897 : }
898 :
899 : /************************************************************************/
900 : /* dataHandlerCbk() */
901 : /************************************************************************/
902 :
903 792 : void OGRGeoRSSLayer::dataHandlerCbk(const char *data, int nLen)
904 : {
905 792 : if (bStopParsing) return;
906 :
907 792 : if (bInGMLGeometry == TRUE || bInSimpleGeometry == TRUE ||
908 : bInGeoLat == TRUE || bInGeoLong == TRUE ||
909 : pszSubElementName != NULL)
910 : {
911 : char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
912 190 : nSubElementValueLen + nLen + 1);
913 190 : if (pszNewSubElementValue == NULL)
914 : {
915 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
916 0 : XML_StopParser(oSchemaParser, XML_FALSE);
917 0 : bStopParsing = TRUE;
918 0 : return;
919 : }
920 190 : pszSubElementValue = pszNewSubElementValue;
921 190 : memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
922 190 : nSubElementValueLen += nLen;
923 : }
924 : }
925 : #endif
926 :
927 : /************************************************************************/
928 : /* GetNextFeature() */
929 : /************************************************************************/
930 :
931 27 : OGRFeature *OGRGeoRSSLayer::GetNextFeature()
932 : {
933 27 : if (bWriteMode)
934 : {
935 : CPLError(CE_Failure, CPLE_NotSupported,
936 0 : "Cannot read features when writing a GeoRSS file");
937 0 : return NULL;
938 : }
939 :
940 27 : if (fpGeoRSS == NULL)
941 0 : return NULL;
942 :
943 27 : if (!bHasReadSchema)
944 4 : LoadSchema();
945 :
946 27 : if (bStopParsing)
947 0 : return NULL;
948 :
949 : #ifdef HAVE_EXPAT
950 27 : if (nFeatureTabIndex < nFeatureTabLength)
951 : {
952 15 : return ppoFeatureTab[nFeatureTabIndex++];
953 : }
954 :
955 12 : if (VSIFEofL(fpGeoRSS))
956 0 : return NULL;
957 :
958 : char aBuf[BUFSIZ];
959 :
960 12 : CPLFree(ppoFeatureTab);
961 12 : ppoFeatureTab = NULL;
962 12 : nFeatureTabLength = 0;
963 12 : nFeatureTabIndex = 0;
964 :
965 : int nDone;
966 12 : do
967 : {
968 : unsigned int nLen =
969 12 : (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGeoRSS );
970 12 : nDone = VSIFEofL(fpGeoRSS);
971 12 : if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
972 : {
973 : CPLError(CE_Failure, CPLE_AppDefined,
974 : "XML parsing of GeoRSS file failed : %s "
975 : "at line %d, column %d",
976 : XML_ErrorString(XML_GetErrorCode(oParser)),
977 : (int)XML_GetCurrentLineNumber(oParser),
978 0 : (int)XML_GetCurrentColumnNumber(oParser));
979 0 : bStopParsing = TRUE;
980 : }
981 : } while (!nDone && !bStopParsing && nFeatureTabLength == 0);
982 :
983 12 : return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
984 : #else
985 : return NULL;
986 : #endif
987 : }
988 :
989 : /************************************************************************/
990 : /* GetSpatialRef() */
991 : /************************************************************************/
992 :
993 20 : OGRSpatialReference *OGRGeoRSSLayer::GetSpatialRef()
994 :
995 : {
996 20 : if (!bWriteMode && !bHasReadSchema)
997 6 : LoadSchema();
998 :
999 20 : return poSRS;
1000 : }
1001 :
1002 : /************************************************************************/
1003 : /* OGRGeoRSSLayerIsStandardFieldInternal() */
1004 : /************************************************************************/
1005 :
1006 91 : static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
1007 : const char** papszNames)
1008 : {
1009 : unsigned int i;
1010 687 : for( i = 0; papszNames[i] != NULL; i++)
1011 : {
1012 681 : if (strcmp(pszName, papszNames[i]) == 0)
1013 : {
1014 74 : return TRUE;
1015 : }
1016 :
1017 607 : const char* pszUnderscore = strchr(papszNames[i], '_');
1018 607 : if (pszUnderscore == NULL)
1019 : {
1020 251 : int nLen = strlen(papszNames[i]);
1021 251 : if (strncmp(pszName, papszNames[i], nLen) == 0)
1022 : {
1023 12 : int k = nLen;
1024 30 : while(pszName[k] >= '0' && pszName[k] <= '9')
1025 6 : k++;
1026 12 : if (pszName[k] == '\0')
1027 3 : return TRUE;
1028 : }
1029 : }
1030 : else
1031 : {
1032 356 : int nLen = pszUnderscore - papszNames[i];
1033 356 : if (strncmp(pszName, papszNames[i], nLen) == 0)
1034 : {
1035 23 : int k = nLen;
1036 60 : while(pszName[k] >= '0' && pszName[k] <= '9')
1037 14 : k++;
1038 23 : if (pszName[k] == '_' && strcmp(pszName + k, pszUnderscore) == 0)
1039 8 : return TRUE;
1040 : }
1041 : }
1042 : }
1043 6 : return FALSE;
1044 : }
1045 :
1046 : /************************************************************************/
1047 : /* OGRGeoRSSLayer::IsStandardField() */
1048 : /************************************************************************/
1049 :
1050 91 : int OGRGeoRSSLayer::IsStandardField(const char* pszName)
1051 : {
1052 91 : if (eFormat == GEORSS_RSS)
1053 : {
1054 : return OGRGeoRSSLayerIsStandardFieldInternal(pszName,
1055 69 : apszAllowedRSSFieldNames);
1056 : }
1057 : else
1058 : {
1059 : return OGRGeoRSSLayerIsStandardFieldInternal(pszName,
1060 22 : apszAllowedATOMFieldNames);
1061 : }
1062 : }
1063 :
1064 : /************************************************************************/
1065 : /* OGRGeoRSSLayerSplitComposedField() */
1066 : /************************************************************************/
1067 :
1068 103 : static void OGRGeoRSSLayerSplitComposedField(const char* pszName,
1069 : char** ppszElementName,
1070 : char** ppszNumber,
1071 : char** ppszAttributeName)
1072 : {
1073 103 : *ppszElementName = CPLStrdup(pszName);
1074 :
1075 103 : int i = 0;
1076 2180 : while(pszName[i] != '\0' && pszName[i] != '_' &&
1077 1326 : !(pszName[i] >= '0' && pszName[i] <= '9'))
1078 : {
1079 648 : i++;
1080 : }
1081 :
1082 103 : (*ppszElementName)[i] = '\0';
1083 :
1084 118 : if (pszName[i] >= '0' && pszName[i] <= '9')
1085 : {
1086 15 : *ppszNumber = CPLStrdup(pszName + i);
1087 15 : char* pszUnderscore = strchr(*ppszNumber, '_');
1088 15 : if (pszUnderscore)
1089 : {
1090 11 : *pszUnderscore = '\0';
1091 11 : *ppszAttributeName = CPLStrdup(pszUnderscore + 1);
1092 : }
1093 : else
1094 : {
1095 4 : *ppszAttributeName = NULL;
1096 : }
1097 : }
1098 : else
1099 : {
1100 88 : *ppszNumber = CPLStrdup("");
1101 88 : if (pszName[i] == '_')
1102 : {
1103 29 : *ppszAttributeName = CPLStrdup(pszName + i + 1);
1104 : }
1105 : else
1106 : {
1107 59 : *ppszAttributeName = NULL;
1108 : }
1109 : }
1110 103 : }
1111 :
1112 : /************************************************************************/
1113 : /* OGRGeoRSSLayerWriteSimpleElement() */
1114 : /************************************************************************/
1115 :
1116 8 : static void OGRGeoRSSLayerWriteSimpleElement(VSILFILE* fp,
1117 : const char* pszElementName,
1118 : const char* pszNumber,
1119 : const char** papszNames,
1120 : OGRFeatureDefn* poFeatureDefn,
1121 : OGRFeature* poFeature)
1122 : {
1123 8 : VSIFPrintfL(fp, " <%s", pszElementName);
1124 :
1125 : unsigned k;
1126 152 : for( k = 0; papszNames[k] != NULL ; k++)
1127 : {
1128 184 : if (strncmp(papszNames[k], pszElementName, strlen(pszElementName)) == 0 &&
1129 40 : papszNames[k][strlen(pszElementName)] == '_')
1130 : {
1131 14 : const char* pszAttributeName = papszNames[k] + strlen(pszElementName) + 1;
1132 14 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s%s_%s", pszElementName, pszNumber, pszAttributeName));
1133 14 : int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1134 14 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1135 : {
1136 : char* pszValue =
1137 13 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1138 13 : if (poFeatureDefn->GetFieldDefn(iIndex)->GetType() == OFTReal)
1139 : {
1140 0 : char* pszComma = strchr(pszValue, ',');
1141 0 : if (pszComma)
1142 0 : *pszComma = '.';
1143 : }
1144 13 : VSIFPrintfL(fp, " %s=\"%s\"", pszAttributeName, pszValue);
1145 13 : CPLFree(pszValue);
1146 : }
1147 14 : CPLFree(pszFieldName);
1148 : }
1149 : }
1150 :
1151 8 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s%s", pszElementName, pszNumber));
1152 8 : int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1153 8 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1154 : {
1155 6 : VSIFPrintfL(fp, ">");
1156 :
1157 : char* pszValue =
1158 6 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1159 6 : if (poFeatureDefn->GetFieldDefn(iIndex)->GetType() == OFTReal)
1160 : {
1161 0 : char* pszComma = strchr(pszValue, ',');
1162 0 : if (pszComma)
1163 0 : *pszComma = '.';
1164 : }
1165 6 : VSIFPrintfL(fp, "%s", pszValue);
1166 6 : CPLFree(pszValue);
1167 :
1168 6 : VSIFPrintfL(fp, "</%s>\n", pszElementName);
1169 : }
1170 : else
1171 : {
1172 2 : VSIFPrintfL(fp, "/>\n");
1173 : }
1174 8 : CPLFree(pszFieldName);
1175 8 : }
1176 :
1177 : /************************************************************************/
1178 : /* CreateFeature() */
1179 : /************************************************************************/
1180 :
1181 15 : OGRErr OGRGeoRSSLayer::CreateFeature( OGRFeature *poFeature )
1182 :
1183 : {
1184 15 : VSILFILE* fp = poDS->GetOutputFP();
1185 15 : if (fp == NULL)
1186 0 : return CE_Failure;
1187 :
1188 15 : nNextFID ++;
1189 :
1190 : /* Verify that compulsory feeds are set. Otherwise put some default value in them */
1191 15 : if (eFormat == GEORSS_RSS)
1192 : {
1193 14 : int iFieldTitle = poFeatureDefn->GetFieldIndex( "title" );
1194 14 : int iFieldDescription = poFeatureDefn->GetFieldIndex( "description" );
1195 :
1196 14 : VSIFPrintfL(fp, " <item>\n");
1197 :
1198 14 : if ((iFieldTitle == -1 || poFeature->IsFieldSet( iFieldTitle ) == FALSE) &&
1199 : (iFieldDescription == -1 || poFeature->IsFieldSet( iFieldDescription ) == FALSE))
1200 : {
1201 2 : VSIFPrintfL(fp, " <title>Feature %d</title>\n", nNextFID);
1202 : }
1203 : }
1204 : else
1205 : {
1206 1 : VSIFPrintfL(fp, " <entry>\n");
1207 :
1208 1 : int iFieldId = poFeatureDefn->GetFieldIndex( "id" );
1209 1 : int iFieldTitle = poFeatureDefn->GetFieldIndex( "title" );
1210 1 : int iFieldUpdated = poFeatureDefn->GetFieldIndex( "updated" );
1211 :
1212 1 : if (iFieldId == -1 || poFeature->IsFieldSet( iFieldId ) == FALSE)
1213 : {
1214 0 : VSIFPrintfL(fp, " <id>Feature %d</id>\n", nNextFID);
1215 : }
1216 :
1217 1 : if (iFieldTitle == -1 || poFeature->IsFieldSet( iFieldTitle ) == FALSE)
1218 : {
1219 0 : VSIFPrintfL(fp, " <title>Title for feature %d</title>\n", nNextFID);
1220 : }
1221 :
1222 1 : if (iFieldUpdated == -1 || poFeature->IsFieldSet(iFieldUpdated ) == FALSE)
1223 : {
1224 0 : VSIFPrintfL(fp, " <updated>2009-01-01T00:00:00Z</updated>\n");
1225 : }
1226 : }
1227 :
1228 15 : int nFieldCount = poFeatureDefn->GetFieldCount();
1229 15 : int* pbUsed = (int*)CPLCalloc(sizeof(int), nFieldCount);
1230 :
1231 146 : for(int i = 0; i < nFieldCount; i ++)
1232 : {
1233 131 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
1234 131 : const char* pszName = poFieldDefn->GetNameRef();
1235 :
1236 131 : if ( ! poFeature->IsFieldSet( i ) )
1237 48 : continue;
1238 :
1239 : char* pszElementName;
1240 : char* pszNumber;
1241 : char* pszAttributeName;
1242 83 : OGRGeoRSSLayerSplitComposedField(pszName, &pszElementName, &pszNumber, &pszAttributeName);
1243 :
1244 83 : int bWillSkip = FALSE;
1245 : /* Handle Atom entries with elements with sub-elements like */
1246 : /* <author><name>...</name><uri>...</uri></author */
1247 83 : if (eFormat == GEORSS_ATOM)
1248 : {
1249 : unsigned int k;
1250 52 : for (k=0;apszAllowedATOMFieldNamesWithSubElements[k] != NULL;k++)
1251 : {
1252 37 : if (strcmp(pszElementName, apszAllowedATOMFieldNamesWithSubElements[k]) == 0 &&
1253 : pszAttributeName != NULL)
1254 : {
1255 5 : bWillSkip = TRUE;
1256 5 : if (pbUsed[i])
1257 2 : break;
1258 :
1259 3 : VSIFPrintfL(fp, " <%s>\n", pszElementName);
1260 :
1261 : int j;
1262 23 : for(j = i; j < nFieldCount; j ++)
1263 : {
1264 20 : poFieldDefn = poFeatureDefn->GetFieldDefn( j );
1265 20 : if ( ! poFeature->IsFieldSet( j ) )
1266 0 : continue;
1267 :
1268 : char* pszElementName2;
1269 : char* pszNumber2;
1270 : char* pszAttributeName2;
1271 : OGRGeoRSSLayerSplitComposedField(poFieldDefn->GetNameRef(),
1272 20 : &pszElementName2, &pszNumber2, &pszAttributeName2);
1273 :
1274 20 : if (strcmp(pszElementName2, pszElementName) == 0 &&
1275 : strcmp(pszNumber, pszNumber2) == 0 && pszAttributeName2 != NULL)
1276 : {
1277 5 : pbUsed[j] = TRUE;
1278 :
1279 : char* pszValue =
1280 5 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( j ));
1281 5 : if (poFeatureDefn->GetFieldDefn(j)->GetType() == OFTReal)
1282 : {
1283 0 : char* pszComma = strchr(pszValue, ',');
1284 0 : if (pszComma)
1285 0 : *pszComma = '.';
1286 : }
1287 5 : VSIFPrintfL(fp, " <%s>%s</%s>\n", pszAttributeName2, pszValue, pszAttributeName2);
1288 5 : CPLFree(pszValue);
1289 : }
1290 20 : CPLFree(pszElementName2);
1291 20 : CPLFree(pszNumber2);
1292 20 : CPLFree(pszAttributeName2);
1293 : }
1294 :
1295 3 : VSIFPrintfL(fp, " </%s>\n", pszElementName);
1296 :
1297 3 : break;
1298 : }
1299 : }
1300 : }
1301 :
1302 83 : if (bWillSkip)
1303 : {
1304 : /* Do nothing */
1305 : }
1306 90 : else if (eFormat == GEORSS_RSS &&
1307 : strcmp(pszName, "pubDate") == 0)
1308 : {
1309 : int year, month, day, hour, minute, second, TZFlag;
1310 12 : if (poFeature->GetFieldAsDateTime(i, &year, &month, &day,
1311 : &hour, &minute, &second, &TZFlag))
1312 : {
1313 12 : char* pszDate = OGRGetRFC822DateTime(year, month, day, hour, minute, second, TZFlag);
1314 : VSIFPrintfL(fp, " <%s>%s</%s>\n",
1315 12 : pszName, pszDate, pszName);
1316 12 : CPLFree(pszDate);
1317 : }
1318 : }
1319 68 : else if (eFormat == GEORSS_ATOM &&
1320 : (strcmp(pszName, "updated") == 0 || strcmp(pszName, "published") == 0))
1321 : {
1322 : int year, month, day, hour, minute, second, TZFlag;
1323 2 : if (poFeature->GetFieldAsDateTime(i, &year, &month, &day,
1324 : &hour, &minute, &second, &TZFlag))
1325 : {
1326 2 : char* pszDate = OGRGetXMLDateTime(year, month, day, hour, minute, second, TZFlag);
1327 : VSIFPrintfL(fp, " <%s>%s</%s>\n",
1328 2 : pszName, pszDate, pszName);
1329 2 : CPLFree(pszDate);
1330 : }
1331 : }
1332 64 : else if (strcmp(pszName, "dc_date") == 0)
1333 : {
1334 : int year, month, day, hour, minute, second, TZFlag;
1335 0 : if (poFeature->GetFieldAsDateTime(i, &year, &month, &day,
1336 : &hour, &minute, &second, &TZFlag))
1337 : {
1338 0 : char* pszDate = OGRGetXMLDateTime(year, month, day, hour, minute, second, TZFlag);
1339 : VSIFPrintfL(fp, " <%s>%s</%s>\n",
1340 0 : "dc:date", pszDate, "dc:date");
1341 0 : CPLFree(pszDate);
1342 : }
1343 : }
1344 : /* RSS fields with content and attributes */
1345 76 : else if (eFormat == GEORSS_RSS &&
1346 : (strcmp(pszElementName, "category") == 0 ||
1347 : strcmp(pszElementName, "guid") == 0 ||
1348 : strcmp(pszElementName, "source") == 0 ))
1349 : {
1350 12 : if (pszAttributeName == NULL)
1351 : {
1352 : OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
1353 6 : apszAllowedRSSFieldNames, poFeatureDefn, poFeature);
1354 : }
1355 : }
1356 : /* RSS field with attribute only */
1357 52 : else if (eFormat == GEORSS_RSS &&
1358 : strcmp(pszElementName, "enclosure") == 0)
1359 : {
1360 0 : if (pszAttributeName != NULL && strcmp(pszAttributeName, "url") == 0)
1361 : {
1362 : OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
1363 0 : apszAllowedRSSFieldNames, poFeatureDefn, poFeature);
1364 : }
1365 : }
1366 : /* ATOM fields with attribute only */
1367 59 : else if (eFormat == GEORSS_ATOM &&
1368 : (strcmp(pszElementName, "category") == 0 || strcmp(pszElementName, "link") == 0))
1369 : {
1370 7 : if (pszAttributeName != NULL &&
1371 : ((strcmp(pszElementName, "category") == 0 && strcmp(pszAttributeName, "term") == 0) ||
1372 : (strcmp(pszElementName, "link") == 0 && strcmp(pszAttributeName, "href") == 0)))
1373 : {
1374 : OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
1375 2 : apszAllowedATOMFieldNames, poFeatureDefn, poFeature);
1376 : }
1377 : }
1378 49 : else if (eFormat == GEORSS_ATOM &&
1379 : (strncmp(pszName, "content", strlen("content")) == 0 ||
1380 : strncmp(pszName, "summary", strlen("summary")) == 0))
1381 : {
1382 : char* pszFieldName;
1383 : int iIndex;
1384 4 : if (strchr(pszName, '_') == NULL)
1385 : {
1386 1 : VSIFPrintfL(fp, " <%s", pszName);
1387 :
1388 1 : int bIsXHTML = FALSE;
1389 1 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "type"));
1390 1 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1391 1 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1392 : {
1393 1 : bIsXHTML = strcmp(poFeature->GetFieldAsString( iIndex ), "xhtml") == 0;
1394 : char* pszValue =
1395 1 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1396 1 : VSIFPrintfL(fp, " %s=\"%s\"", "type", pszValue);
1397 1 : CPLFree(pszValue);
1398 : }
1399 1 : CPLFree(pszFieldName);
1400 :
1401 1 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
1402 1 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1403 1 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1404 : {
1405 : char* pszValue =
1406 1 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1407 1 : VSIFPrintfL(fp, " %s=\"%s\"", "xml:lang", pszValue);
1408 1 : CPLFree(pszValue);
1409 : }
1410 1 : CPLFree(pszFieldName);
1411 :
1412 1 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_base"));
1413 1 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1414 1 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1415 : {
1416 : char* pszValue =
1417 1 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1418 1 : VSIFPrintfL(fp, " %s=\"%s\"", "xml:base", pszValue);
1419 1 : CPLFree(pszValue);
1420 : }
1421 1 : CPLFree(pszFieldName);
1422 :
1423 1 : VSIFPrintfL(fp, ">");
1424 1 : if (bIsXHTML)
1425 1 : VSIFPrintfL(fp, "%s", poFeature->GetFieldAsString(i));
1426 : else
1427 : {
1428 : char* pszValue =
1429 0 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
1430 0 : VSIFPrintfL(fp, "%s", pszValue);
1431 0 : CPLFree(pszValue);
1432 : }
1433 1 : VSIFPrintfL(fp, " </%s>\n", pszName);
1434 : }
1435 : }
1436 41 : else if (strncmp(pszName, "dc_subject", strlen("dc_subject")) == 0)
1437 : {
1438 : char* pszFieldName;
1439 : int iIndex;
1440 0 : if (strchr(pszName+strlen("dc_subject"), '_') == NULL)
1441 : {
1442 0 : VSIFPrintfL(fp, " <%s", "dc:subject");
1443 :
1444 0 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
1445 0 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1446 0 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1447 : {
1448 : char* pszValue =
1449 0 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1450 0 : VSIFPrintfL(fp, " %s=\"%s\"", "xml:lang", pszValue);
1451 0 : CPLFree(pszValue);
1452 : }
1453 0 : CPLFree(pszFieldName);
1454 :
1455 : char* pszValue =
1456 0 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
1457 0 : VSIFPrintfL(fp, ">%s</%s>\n", pszValue, "dc:subject");
1458 0 : CPLFree(pszValue);
1459 : }
1460 : }
1461 : else
1462 : {
1463 41 : char* pszTagName = CPLStrdup(pszName);
1464 41 : if (IsStandardField(pszName) == FALSE)
1465 : {
1466 : int j;
1467 3 : int nCountUnderscore = 0;
1468 29 : for(j=0;pszTagName[j] != 0;j++)
1469 : {
1470 26 : if (pszTagName[j] == '_')
1471 : {
1472 2 : if (nCountUnderscore == 0)
1473 2 : pszTagName[j] = ':';
1474 2 : nCountUnderscore ++;
1475 : }
1476 24 : else if (pszTagName[j] == ' ')
1477 0 : pszTagName[j] = '_';
1478 : }
1479 3 : if (nCountUnderscore == 0)
1480 : {
1481 1 : char* pszTemp = CPLStrdup(CPLSPrintf("ogr:%s", pszTagName));
1482 1 : CPLFree(pszTagName);
1483 1 : pszTagName = pszTemp;
1484 : }
1485 : }
1486 : char* pszValue =
1487 41 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
1488 41 : if (poFeatureDefn->GetFieldDefn(i)->GetType() == OFTReal)
1489 : {
1490 0 : char* pszComma = strchr(pszValue, ',');
1491 0 : if (pszComma)
1492 0 : *pszComma = '.';
1493 : }
1494 41 : VSIFPrintfL(fp, " <%s>%s</%s>\n", pszTagName, pszValue, pszTagName);
1495 41 : CPLFree(pszValue);
1496 41 : CPLFree(pszTagName);
1497 : }
1498 :
1499 83 : CPLFree(pszElementName);
1500 83 : CPLFree(pszNumber);
1501 83 : CPLFree(pszAttributeName);
1502 : }
1503 :
1504 15 : CPLFree(pbUsed);
1505 :
1506 15 : OGRGeoRSSGeomDialect eGeomDialect = poDS->GetGeomDialect();
1507 15 : OGRGeometry* poGeom = poFeature->GetGeometryRef();
1508 15 : if ( poGeom != NULL && !poGeom->IsEmpty() )
1509 : {
1510 13 : char* pszURN = NULL;
1511 13 : int bSwapCoordinates = FALSE;
1512 13 : if (eGeomDialect == GEORSS_GML)
1513 : {
1514 5 : if (poSRS != NULL)
1515 : {
1516 1 : const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
1517 1 : const char* pszAuthorityCode = poSRS->GetAuthorityCode(NULL);
1518 2 : if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG") &&
1519 : pszAuthorityCode != NULL)
1520 : {
1521 1 : if (!EQUAL(pszAuthorityCode, "4326"))
1522 1 : pszURN = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszAuthorityCode));
1523 :
1524 : /* In case the SRS is a geographic SRS and that we have no axis */
1525 : /* defintion, we assume that the order is lon/lat */
1526 1 : const char* pszAxisName = poSRS->GetAxis(NULL, 0, NULL);
1527 1 : if (poSRS->IsGeographic() &&
1528 : (pszAxisName == NULL || EQUALN(pszAxisName, "Lon", 3)))
1529 : {
1530 0 : bSwapCoordinates = TRUE;
1531 : }
1532 : }
1533 : else
1534 : {
1535 : static int bOnce = FALSE;
1536 0 : if (!bOnce)
1537 : {
1538 0 : bOnce = TRUE;
1539 0 : CPLError(CE_Warning, CPLE_AppDefined, "Could not translate SRS into GML urn");
1540 : }
1541 : }
1542 : }
1543 : else
1544 : {
1545 4 : bSwapCoordinates = TRUE;
1546 : }
1547 : }
1548 :
1549 : char szCoord[75];
1550 13 : switch( wkbFlatten(poGeom->getGeometryType()) )
1551 : {
1552 : case wkbPoint:
1553 : {
1554 4 : OGRPoint* poPoint = (OGRPoint*)poGeom;
1555 4 : double x = poPoint->getX();
1556 4 : double y = poPoint->getY();
1557 4 : if (eGeomDialect == GEORSS_GML)
1558 : {
1559 2 : VSIFPrintfL(fp, " <georss:where><gml:Point");
1560 2 : if (pszURN != NULL)
1561 1 : VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
1562 2 : if (poGeom->getCoordinateDimension() == 3)
1563 : {
1564 : OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
1565 0 : poPoint->getZ(), 3);
1566 0 : VSIFPrintfL(fp, " srsDimension=\"3\"><gml:pos>%s", szCoord);
1567 : }
1568 : else
1569 : {
1570 : OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
1571 2 : 0, 2);
1572 2 : VSIFPrintfL(fp, "><gml:pos>%s", szCoord);
1573 : }
1574 2 : VSIFPrintfL(fp, "</gml:pos></gml:Point></georss:where>\n");
1575 : }
1576 2 : else if (eGeomDialect == GEORSS_SIMPLE)
1577 : {
1578 1 : OGRMakeWktCoordinate(szCoord, y, x, 0, 2);
1579 1 : VSIFPrintfL(fp, " <georss:point>%s</georss:point>\n", szCoord);
1580 : }
1581 1 : else if (eGeomDialect == GEORSS_W3C_GEO)
1582 : {
1583 1 : OGRFormatDouble( szCoord, sizeof(szCoord), y, '.' );
1584 1 : VSIFPrintfL(fp, " <geo:lat>%s</geo:lat>\n", szCoord);
1585 1 : OGRFormatDouble( szCoord, sizeof(szCoord), x, '.' );
1586 1 : VSIFPrintfL(fp, " <geo:long>%s</geo:long>\n", szCoord);
1587 : }
1588 4 : break;
1589 : }
1590 :
1591 : case wkbLineString:
1592 : {
1593 3 : OGRLineString* poLineString = (OGRLineString*)poGeom;
1594 3 : if (eGeomDialect == GEORSS_GML)
1595 : {
1596 1 : VSIFPrintfL(fp, " <georss:where><gml:LineString");
1597 1 : if (pszURN != NULL)
1598 0 : VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
1599 1 : VSIFPrintfL(fp, "><gml:posList>\n");
1600 1 : int n = poLineString->getNumPoints();
1601 4 : for(int i=0;i<n;i++)
1602 : {
1603 3 : double x = poLineString->getX(i);
1604 3 : double y = poLineString->getY(i);
1605 : OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
1606 3 : 0, 2);
1607 3 : VSIFPrintfL(fp, "%s ", szCoord);
1608 : }
1609 1 : VSIFPrintfL(fp, "</gml:posList></gml:LineString></georss:where>\n");
1610 : }
1611 2 : else if (eGeomDialect == GEORSS_SIMPLE)
1612 : {
1613 1 : VSIFPrintfL(fp, " <georss:line>\n");
1614 1 : int n = poLineString->getNumPoints();
1615 4 : for(int i=0;i<n;i++)
1616 : {
1617 3 : double x = poLineString->getX(i);
1618 3 : double y = poLineString->getY(i);
1619 3 : OGRMakeWktCoordinate(szCoord, y, x, 0, 2);
1620 3 : VSIFPrintfL(fp, "%s ", szCoord);
1621 : }
1622 1 : VSIFPrintfL(fp, "</georss:line>\n");
1623 : }
1624 : else
1625 : {
1626 : /* Not supported */
1627 : }
1628 3 : break;
1629 : }
1630 :
1631 : case wkbPolygon:
1632 : {
1633 6 : OGRPolygon* poPolygon = (OGRPolygon*)poGeom;
1634 6 : OGRLineString* poLineString = poPolygon->getExteriorRing();
1635 6 : if (poLineString == NULL)
1636 0 : break;
1637 :
1638 6 : if (eGeomDialect == GEORSS_GML)
1639 : {
1640 2 : VSIFPrintfL(fp, " <georss:where><gml:Polygon");
1641 2 : if (pszURN != NULL)
1642 0 : VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
1643 2 : VSIFPrintfL(fp, "><gml:exterior><gml:LinearRing><gml:posList>\n");
1644 2 : int n = poLineString->getNumPoints();
1645 12 : for(int i=0;i<n;i++)
1646 : {
1647 10 : double x = poLineString->getX(i);
1648 10 : double y = poLineString->getY(i);
1649 : OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
1650 10 : 0, 2);
1651 10 : VSIFPrintfL(fp, "%s ", szCoord);
1652 : }
1653 2 : VSIFPrintfL(fp, "</gml:posList></gml:LinearRing></gml:exterior></gml:Polygon></georss:where>\n");
1654 : }
1655 4 : else if (eGeomDialect == GEORSS_SIMPLE)
1656 : {
1657 2 : VSIFPrintfL(fp, " <georss:polygon>\n");
1658 2 : int n = poLineString->getNumPoints();
1659 12 : for(int i=0;i<n;i++)
1660 : {
1661 10 : double x = poLineString->getX(i);
1662 10 : double y = poLineString->getY(i);
1663 10 : OGRMakeWktCoordinate(szCoord, y, x, 0, 2);
1664 10 : VSIFPrintfL(fp, "%s ", szCoord);
1665 : }
1666 2 : VSIFPrintfL(fp, "</georss:polygon>\n");
1667 : }
1668 : else
1669 : {
1670 : /* Not supported */
1671 : }
1672 : break;
1673 : }
1674 :
1675 : default:
1676 : /* Not supported */
1677 : break;
1678 : }
1679 13 : CPLFree(pszURN);
1680 : }
1681 :
1682 15 : if (eFormat == GEORSS_RSS)
1683 14 : VSIFPrintfL(fp, " </item>\n");
1684 : else
1685 1 : VSIFPrintfL(fp, " </entry>\n");
1686 :
1687 15 : return OGRERR_NONE;
1688 : }
1689 :
1690 :
1691 :
1692 : /************************************************************************/
1693 : /* CreateField() */
1694 : /************************************************************************/
1695 :
1696 50 : OGRErr OGRGeoRSSLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
1697 :
1698 : {
1699 50 : const char* pszName = poFieldDefn->GetNameRef();
1700 50 : if (((eFormat == GEORSS_RSS && strcmp(pszName, "pubDate") == 0) ||
1701 : (eFormat == GEORSS_ATOM && (strcmp(pszName, "updated") == 0 ||
1702 : strcmp(pszName, "published") == 0 )) ||
1703 : strcmp(pszName, "dc:date") == 0) &&
1704 : poFieldDefn->GetType() != OFTDateTime)
1705 : {
1706 0 : CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s", pszName);
1707 0 : return OGRERR_FAILURE;
1708 : }
1709 :
1710 351 : for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
1711 : {
1712 301 : if (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
1713 : pszName ) == 0)
1714 : {
1715 0 : return OGRERR_FAILURE;
1716 : }
1717 : }
1718 :
1719 50 : if (IsStandardField(pszName))
1720 : {
1721 47 : poFeatureDefn->AddFieldDefn( poFieldDefn );
1722 47 : return OGRERR_NONE;
1723 : }
1724 :
1725 3 : if (poDS->GetUseExtensions() == FALSE)
1726 : {
1727 : CPLError(CE_Failure, CPLE_NotSupported,
1728 : "Field of name '%s' is not supported in %s schema. "
1729 : "Use USE_EXTENSIONS creation option to allow use of extensions.",
1730 0 : pszName, (eFormat == GEORSS_RSS) ? "RSS" : "ATOM");
1731 0 : return OGRERR_FAILURE;
1732 : }
1733 : else
1734 : {
1735 3 : poFeatureDefn->AddFieldDefn( poFieldDefn );
1736 3 : return OGRERR_NONE;
1737 : }
1738 : }
1739 :
1740 : #ifdef HAVE_EXPAT
1741 :
1742 276 : static void XMLCALL startElementLoadSchemaCbk(void *pUserData, const char *pszName, const char **ppszAttr)
1743 : {
1744 276 : ((OGRGeoRSSLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
1745 276 : }
1746 :
1747 276 : static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
1748 : {
1749 276 : ((OGRGeoRSSLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
1750 276 : }
1751 :
1752 792 : static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData, const char *data, int nLen)
1753 : {
1754 792 : ((OGRGeoRSSLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
1755 792 : }
1756 :
1757 :
1758 : /************************************************************************/
1759 : /* LoadSchema() */
1760 : /************************************************************************/
1761 :
1762 : /** This function parses the whole file to detect the fields */
1763 18 : void OGRGeoRSSLayer::LoadSchema()
1764 : {
1765 18 : if (bHasReadSchema)
1766 0 : return;
1767 :
1768 18 : bHasReadSchema = TRUE;
1769 :
1770 18 : if (fpGeoRSS == NULL)
1771 6 : return;
1772 :
1773 12 : oSchemaParser = OGRCreateExpatXMLParser();
1774 12 : XML_SetElementHandler(oSchemaParser, ::startElementLoadSchemaCbk, ::endElementLoadSchemaCbk);
1775 12 : XML_SetCharacterDataHandler(oSchemaParser, ::dataHandlerLoadSchemaCbk);
1776 12 : XML_SetUserData(oSchemaParser, this);
1777 :
1778 12 : VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
1779 :
1780 12 : bInFeature = FALSE;
1781 12 : currentDepth = 0;
1782 12 : currentFieldDefn = NULL;
1783 12 : pszSubElementName = NULL;
1784 12 : pszSubElementValue = NULL;
1785 12 : nSubElementValueLen = 0;
1786 12 : bSameSRS = TRUE;
1787 12 : CPLFree(pszGMLSRSName);
1788 12 : pszGMLSRSName = NULL;
1789 12 : eGeomType = wkbUnknown;
1790 12 : bFoundGeom = FALSE;
1791 12 : bInTagWithSubTag = FALSE;
1792 12 : pszTagWithSubTag = NULL;
1793 12 : bStopParsing = FALSE;
1794 12 : nWithoutEventCounter = 0;
1795 12 : nTotalFeatureCount = 0;
1796 12 : setOfFoundFields = NULL;
1797 :
1798 : char aBuf[BUFSIZ];
1799 : int nDone;
1800 12 : do
1801 : {
1802 12 : nDataHandlerCounter = 0;
1803 12 : unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGeoRSS );
1804 12 : nDone = VSIFEofL(fpGeoRSS);
1805 12 : if (XML_Parse(oSchemaParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
1806 : {
1807 : CPLError(CE_Failure, CPLE_AppDefined,
1808 : "XML parsing of GeoRSS file failed : %s at line %d, column %d",
1809 : XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
1810 : (int)XML_GetCurrentLineNumber(oSchemaParser),
1811 0 : (int)XML_GetCurrentColumnNumber(oSchemaParser));
1812 0 : bStopParsing = TRUE;
1813 : }
1814 12 : nWithoutEventCounter ++;
1815 : } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
1816 :
1817 12 : XML_ParserFree(oSchemaParser);
1818 :
1819 12 : if (nWithoutEventCounter == 10)
1820 : {
1821 : CPLError(CE_Failure, CPLE_AppDefined,
1822 0 : "Too much data inside one element. File probably corrupted");
1823 0 : bStopParsing = TRUE;
1824 : }
1825 :
1826 12 : CPLAssert(poSRS == NULL);
1827 12 : if (bSameSRS && bFoundGeom)
1828 : {
1829 9 : if (pszGMLSRSName == NULL)
1830 : {
1831 8 : poSRS = new OGRSpatialReference();
1832 8 : poSRS->SetWellKnownGeogCS( "WGS84" ); /* no AXIS definition ! */
1833 : }
1834 : else
1835 : {
1836 1 : poSRS = new OGRSpatialReference();
1837 1 : poSRS->importFromURN(pszGMLSRSName);
1838 : }
1839 : }
1840 :
1841 12 : if (eGeomType != wkbUnknown)
1842 5 : poFeatureDefn->SetGeomType(eGeomType);
1843 :
1844 12 : if (setOfFoundFields)
1845 12 : CPLHashSetDestroy(setOfFoundFields);
1846 12 : setOfFoundFields = NULL;
1847 12 : CPLFree(pszGMLSRSName);
1848 12 : pszGMLSRSName = NULL;
1849 12 : CPLFree(pszTagWithSubTag);
1850 12 : pszTagWithSubTag = NULL;
1851 :
1852 12 : VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
1853 : }
1854 :
1855 :
1856 : /************************************************************************/
1857 : /* OGRGeoRSSIsInt() */
1858 : /************************************************************************/
1859 :
1860 3 : static int OGRGeoRSSIsInt(const char* pszStr)
1861 : {
1862 : int i;
1863 :
1864 6 : while(*pszStr == ' ')
1865 0 : pszStr++;
1866 :
1867 12 : for(i=0;pszStr[i];i++)
1868 : {
1869 9 : if (pszStr[i] == '+' || pszStr[i] == '-')
1870 : {
1871 0 : if (i != 0)
1872 0 : return FALSE;
1873 : }
1874 9 : else if (!(pszStr[i] >= '0' && pszStr[i] <= '9'))
1875 0 : return FALSE;
1876 : }
1877 3 : return TRUE;
1878 : }
1879 :
1880 : /************************************************************************/
1881 : /* startElementLoadSchemaCbk() */
1882 : /************************************************************************/
1883 :
1884 276 : void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr)
1885 : {
1886 276 : if (bStopParsing) return;
1887 :
1888 276 : nWithoutEventCounter = 0;
1889 :
1890 303 : if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
1891 : ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && !bInFeature && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
1892 : {
1893 27 : bInFeature = TRUE;
1894 27 : featureDepth = currentDepth;
1895 :
1896 27 : nTotalFeatureCount ++;
1897 :
1898 27 : if (setOfFoundFields)
1899 15 : CPLHashSetDestroy(setOfFoundFields);
1900 27 : setOfFoundFields = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
1901 : }
1902 259 : else if (bInTagWithSubTag && currentDepth == 3)
1903 : {
1904 10 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszName));
1905 10 : if (poFeatureDefn->GetFieldIndex(pszFieldName) == -1)
1906 : {
1907 10 : OGRFieldDefn newFieldDefn(pszFieldName, OFTString);
1908 10 : poFeatureDefn->AddFieldDefn(&newFieldDefn);
1909 :
1910 10 : if (poFeatureDefn->GetFieldCount() == 100)
1911 : {
1912 : CPLError(CE_Failure, CPLE_AppDefined,
1913 0 : "Too many fields. File probably corrupted");
1914 0 : XML_StopParser(oSchemaParser, XML_FALSE);
1915 0 : bStopParsing = TRUE;
1916 10 : }
1917 : }
1918 10 : CPLFree(pszFieldName);
1919 : }
1920 239 : else if (bInFeature && eFormat == GEORSS_ATOM &&
1921 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
1922 : {
1923 6 : CPLFree(pszTagWithSubTag);
1924 6 : pszTagWithSubTag = CPLStrdup(pszName);
1925 :
1926 6 : int count = 1;
1927 14 : while(CPLHashSetLookup(setOfFoundFields, pszTagWithSubTag) != NULL)
1928 : {
1929 2 : count ++;
1930 2 : CPLFree(pszTagWithSubTag);
1931 2 : pszTagWithSubTag = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
1932 2 : if (pszTagWithSubTag[0] == 0)
1933 : {
1934 0 : XML_StopParser(oSchemaParser, XML_FALSE);
1935 0 : bStopParsing = TRUE;
1936 0 : break;
1937 : }
1938 : }
1939 6 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
1940 :
1941 6 : bInTagWithSubTag = TRUE;
1942 : }
1943 353 : else if (bInFeature && currentDepth == featureDepth + 1 && !IS_GEO_ELEMENT(pszName))
1944 : {
1945 120 : CPLFree(pszSubElementName);
1946 120 : pszSubElementName = CPLStrdup(pszName);
1947 :
1948 120 : int count = 1;
1949 247 : while(CPLHashSetLookup(setOfFoundFields, pszSubElementName) != NULL)
1950 : {
1951 7 : count ++;
1952 7 : CPLFree(pszSubElementName);
1953 7 : pszSubElementName = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
1954 : }
1955 120 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszSubElementName));
1956 :
1957 : /* Create field definition for element */
1958 120 : char* pszCompatibleName = OGRGeoRSS_GetOGRCompatibleTagName(pszSubElementName);
1959 120 : int iField = poFeatureDefn->GetFieldIndex(pszCompatibleName);
1960 120 : if (iField >= 0)
1961 : {
1962 66 : currentFieldDefn = poFeatureDefn->GetFieldDefn(iField);
1963 : }
1964 54 : else if ( ! ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && strcmp(pszName, "enclosure") == 0) &&
1965 : ! (eFormat == GEORSS_ATOM && strcmp(pszName, "link") == 0) &&
1966 : ! (eFormat == GEORSS_ATOM && strcmp(pszName, "category") == 0))
1967 : {
1968 : OGRFieldType eFieldType;
1969 60 : if (((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && strcmp(pszName, "pubDate") == 0) ||
1970 : (eFormat == GEORSS_ATOM && strcmp(pszName, "updated") == 0) ||
1971 : (eFormat == GEORSS_ATOM && strcmp(pszName, "published") == 0) ||
1972 : strcmp(pszName, "dc:date") == 0)
1973 10 : eFieldType = OFTDateTime;
1974 : else
1975 40 : eFieldType = OFTInteger;
1976 :
1977 50 : OGRFieldDefn newFieldDefn(pszCompatibleName, eFieldType);
1978 50 : poFeatureDefn->AddFieldDefn(&newFieldDefn);
1979 50 : currentFieldDefn = poFeatureDefn->GetFieldDefn(poFeatureDefn->GetFieldCount() - 1);
1980 :
1981 50 : if (poFeatureDefn->GetFieldCount() == 100)
1982 : {
1983 : CPLError(CE_Failure, CPLE_AppDefined,
1984 0 : "Too many fields. File probably corrupted");
1985 0 : XML_StopParser(oSchemaParser, XML_FALSE);
1986 0 : bStopParsing = TRUE;
1987 50 : }
1988 : }
1989 :
1990 : /* Create field definitions for attributes */
1991 151 : for(int i=0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL && !bStopParsing; i+= 2)
1992 : {
1993 : char* pszAttrCompatibleName =
1994 31 : OGRGeoRSS_GetOGRCompatibleTagName(CPLSPrintf("%s_%s", pszSubElementName, ppszAttr[i]));
1995 31 : iField = poFeatureDefn->GetFieldIndex(pszAttrCompatibleName);
1996 : OGRFieldDefn* currentAttrFieldDefn;
1997 31 : if (iField >= 0)
1998 : {
1999 0 : currentAttrFieldDefn = poFeatureDefn->GetFieldDefn(iField);
2000 : }
2001 : else
2002 : {
2003 31 : OGRFieldDefn newFieldDefn(pszAttrCompatibleName, OFTInteger);
2004 31 : poFeatureDefn->AddFieldDefn(&newFieldDefn);
2005 31 : currentAttrFieldDefn = poFeatureDefn->GetFieldDefn(poFeatureDefn->GetFieldCount() - 1);
2006 :
2007 31 : if (poFeatureDefn->GetFieldCount() == 100)
2008 : {
2009 : CPLError(CE_Failure, CPLE_AppDefined,
2010 0 : "Too many fields. File probably corrupted");
2011 0 : XML_StopParser(oSchemaParser, XML_FALSE);
2012 0 : bStopParsing = TRUE;
2013 31 : }
2014 : }
2015 31 : if (currentAttrFieldDefn->GetType() == OFTInteger ||
2016 : currentAttrFieldDefn->GetType() == OFTReal)
2017 : {
2018 31 : char* pszRemainingStr = NULL;
2019 31 : CPLStrtod(ppszAttr[i + 1], &pszRemainingStr);
2020 33 : if (pszRemainingStr == NULL ||
2021 : *pszRemainingStr == 0 ||
2022 : *pszRemainingStr == ' ')
2023 : {
2024 2 : if (currentAttrFieldDefn->GetType() == OFTInteger)
2025 : {
2026 2 : if (OGRGeoRSSIsInt(ppszAttr[i + 1]) == FALSE)
2027 : {
2028 0 : currentAttrFieldDefn->SetType(OFTReal);
2029 : }
2030 : }
2031 : }
2032 : else
2033 : {
2034 29 : currentAttrFieldDefn->SetType(OFTString);
2035 : }
2036 : }
2037 31 : CPLFree(pszAttrCompatibleName);
2038 : }
2039 :
2040 120 : CPLFree(pszCompatibleName);
2041 : }
2042 124 : else if (strcmp(pszName, "georss:point") == 0 ||
2043 : strcmp(pszName, "georss:line") == 0 ||
2044 : strcmp(pszName, "geo:line") == 0 ||
2045 : IS_LAT_ELEMENT(pszName) ||
2046 : strcmp(pszName, "georss:polygon") == 0 ||
2047 : strcmp(pszName, "georss:box") == 0)
2048 : {
2049 11 : if (bSameSRS)
2050 : {
2051 11 : if (pszGMLSRSName != NULL)
2052 0 : bSameSRS = FALSE;
2053 : }
2054 : }
2055 102 : else if (strcmp(pszName, "gml:Point") == 0 ||
2056 : strcmp(pszName, "gml:LineString") == 0 ||
2057 : strcmp(pszName, "gml:Polygon") == 0 ||
2058 : strcmp(pszName, "gml:MultiPoint") == 0 ||
2059 : strcmp(pszName, "gml:MultiLineString") == 0 ||
2060 : strcmp(pszName, "gml:MultiPolygon") == 0 ||
2061 : strcmp(pszName, "gml:Envelope") == 0)
2062 : {
2063 10 : if (bSameSRS)
2064 : {
2065 10 : int bFoundSRS = FALSE;
2066 10 : for(int i = 0; ppszAttr[i] != NULL; i+=2)
2067 : {
2068 1 : if (strcmp(ppszAttr[i], "srsName") == 0)
2069 : {
2070 1 : bFoundSRS = TRUE;
2071 1 : if (pszGMLSRSName != NULL)
2072 : {
2073 0 : if (strcmp(pszGMLSRSName , ppszAttr[i+1]) != 0)
2074 0 : bSameSRS = FALSE;
2075 : }
2076 : else
2077 1 : pszGMLSRSName = CPLStrdup(ppszAttr[i+1]);
2078 1 : break;
2079 : }
2080 : }
2081 10 : if (!bFoundSRS && pszGMLSRSName != NULL)
2082 0 : bSameSRS = FALSE;
2083 : }
2084 : }
2085 :
2086 276 : if (!bInFeature || currentDepth >= featureDepth + 1)
2087 : {
2088 249 : int nDimension = 2;
2089 317 : for(int i = 0; ppszAttr[i] != NULL; i+=2)
2090 : {
2091 68 : if (strcmp(ppszAttr[i], "srsDimension") == 0)
2092 : {
2093 0 : nDimension = atoi(ppszAttr[i+1]);
2094 0 : break;
2095 : }
2096 : }
2097 :
2098 249 : OGRwkbGeometryType eFoundGeomType = wkbUnknown;
2099 256 : if (strcmp(pszName, "georss:point") == 0 ||
2100 : IS_LAT_ELEMENT(pszName) ||
2101 : strcmp(pszName, "gml:Point") == 0)
2102 : {
2103 7 : eFoundGeomType = wkbPoint;
2104 : }
2105 242 : else if (strcmp(pszName, "gml:MultiPoint") == 0)
2106 : {
2107 0 : eFoundGeomType = wkbMultiPoint;
2108 : }
2109 247 : else if (strcmp(pszName, "georss:line") == 0 ||
2110 : strcmp(pszName, "geo:line") == 0 ||
2111 : strcmp(pszName, "gml:LineString") == 0)
2112 : {
2113 5 : eFoundGeomType = wkbLineString;
2114 : }
2115 237 : else if (strcmp(pszName, "gml:MultiLineString") == 0)
2116 : {
2117 0 : eFoundGeomType = wkbMultiLineString;
2118 : }
2119 246 : else if (strcmp(pszName, "georss:polygon") == 0 ||
2120 : strcmp(pszName, "gml:Polygon") == 0 ||
2121 : strcmp(pszName, "gml:Envelope") == 0 ||
2122 : strcmp(pszName, "georss:box") == 0)
2123 : {
2124 9 : eFoundGeomType = wkbPolygon;
2125 : }
2126 228 : else if (strcmp(pszName, "gml:MultiPolygon") == 0)
2127 : {
2128 0 : eFoundGeomType = wkbMultiPolygon;
2129 : }
2130 :
2131 249 : if (eFoundGeomType != wkbUnknown)
2132 : {
2133 21 : if (!bFoundGeom)
2134 : {
2135 9 : eGeomType = eFoundGeomType;
2136 9 : bFoundGeom = TRUE;
2137 : }
2138 12 : else if (wkbFlatten(eGeomType) != eFoundGeomType)
2139 12 : eGeomType = wkbUnknown;
2140 :
2141 21 : if (nDimension == 3)
2142 0 : eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
2143 : }
2144 : }
2145 :
2146 276 : currentDepth++;
2147 : }
2148 :
2149 : /************************************************************************/
2150 : /* endElementLoadSchemaCbk() */
2151 : /************************************************************************/
2152 :
2153 276 : void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
2154 : {
2155 276 : if (bStopParsing) return;
2156 :
2157 276 : nWithoutEventCounter = 0;
2158 :
2159 276 : currentDepth--;
2160 :
2161 276 : if (!bInFeature)
2162 58 : return;
2163 :
2164 245 : if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
2165 : ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
2166 : {
2167 27 : bInFeature = FALSE;
2168 : }
2169 191 : else if (bInFeature && eFormat == GEORSS_ATOM &&
2170 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
2171 : {
2172 6 : bInTagWithSubTag = FALSE;
2173 : }
2174 185 : else if (currentDepth == featureDepth + 1 && pszSubElementName)
2175 : {
2176 : /* Patch field type */
2177 120 : if (pszSubElementValue && nSubElementValueLen && currentFieldDefn)
2178 : {
2179 116 : pszSubElementValue[nSubElementValueLen] = 0;
2180 116 : if (currentFieldDefn->GetType() == OFTInteger ||
2181 : currentFieldDefn->GetType() == OFTReal)
2182 : {
2183 40 : char* pszRemainingStr = NULL;
2184 40 : CPLStrtod(pszSubElementValue, &pszRemainingStr);
2185 41 : if (pszRemainingStr == NULL ||
2186 : *pszRemainingStr == 0 ||
2187 : *pszRemainingStr == ' ')
2188 : {
2189 1 : if (currentFieldDefn->GetType() == OFTInteger)
2190 : {
2191 1 : if (OGRGeoRSSIsInt(pszSubElementValue) == FALSE)
2192 : {
2193 0 : currentFieldDefn->SetType(OFTReal);
2194 : }
2195 : }
2196 : }
2197 : else
2198 : {
2199 39 : currentFieldDefn->SetType(OFTString);
2200 : }
2201 : }
2202 : }
2203 :
2204 120 : CPLFree(pszSubElementName);
2205 120 : pszSubElementName = NULL;
2206 120 : CPLFree(pszSubElementValue);
2207 120 : pszSubElementValue = NULL;
2208 120 : nSubElementValueLen = 0;
2209 120 : currentFieldDefn = NULL;
2210 : }
2211 : }
2212 :
2213 : /************************************************************************/
2214 : /* dataHandlerLoadSchemaCbk() */
2215 : /************************************************************************/
2216 :
2217 792 : void OGRGeoRSSLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
2218 : {
2219 792 : if (bStopParsing) return;
2220 :
2221 792 : nDataHandlerCounter ++;
2222 792 : if (nDataHandlerCounter >= BUFSIZ)
2223 : {
2224 0 : CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
2225 0 : XML_StopParser(oSchemaParser, XML_FALSE);
2226 0 : bStopParsing = TRUE;
2227 0 : return;
2228 : }
2229 :
2230 792 : nWithoutEventCounter = 0;
2231 :
2232 792 : if (pszSubElementName)
2233 : {
2234 125 : char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue, nSubElementValueLen + nLen + 1);
2235 125 : if (pszNewSubElementValue == NULL)
2236 : {
2237 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
2238 0 : XML_StopParser(oSchemaParser, XML_FALSE);
2239 0 : bStopParsing = TRUE;
2240 0 : return;
2241 : }
2242 125 : pszSubElementValue = pszNewSubElementValue;
2243 125 : memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
2244 125 : nSubElementValueLen += nLen;
2245 125 : if (nSubElementValueLen > 100000)
2246 : {
2247 : CPLError(CE_Failure, CPLE_AppDefined,
2248 0 : "Too much data inside one element. File probably corrupted");
2249 0 : XML_StopParser(oSchemaParser, XML_FALSE);
2250 0 : bStopParsing = TRUE;
2251 : }
2252 : }
2253 : }
2254 : #else
2255 : void OGRGeoRSSLayer::LoadSchema()
2256 : {
2257 : }
2258 : #endif
2259 :
2260 : /************************************************************************/
2261 : /* TestCapability() */
2262 : /************************************************************************/
2263 :
2264 0 : int OGRGeoRSSLayer::TestCapability( const char * pszCap )
2265 :
2266 : {
2267 0 : if( EQUAL(pszCap,OLCFastFeatureCount) )
2268 : return !bWriteMode && bHasReadSchema &&
2269 0 : m_poFilterGeom == NULL && m_poAttrQuery == NULL;
2270 :
2271 0 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
2272 0 : return TRUE;
2273 :
2274 0 : else if( EQUAL(pszCap,OLCSequentialWrite) )
2275 0 : return bWriteMode;
2276 : else
2277 0 : return FALSE;
2278 : }
2279 :
2280 : /************************************************************************/
2281 : /* GetFeatureCount() */
2282 : /************************************************************************/
2283 :
2284 0 : int OGRGeoRSSLayer::GetFeatureCount( int bForce )
2285 :
2286 : {
2287 0 : if (bWriteMode)
2288 : {
2289 : CPLError(CE_Failure, CPLE_NotSupported,
2290 0 : "Cannot read features when writing a GeoRSS file");
2291 0 : return 0;
2292 : }
2293 :
2294 0 : if (!bHasReadSchema)
2295 0 : LoadSchema();
2296 :
2297 0 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
2298 0 : return OGRLayer::GetFeatureCount( bForce );
2299 : else
2300 0 : return nTotalFeatureCount;
2301 : }
|