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 38 : OGRGeoRSSLayer::OGRGeoRSSLayer( const char* pszFilename,
82 : const char* pszLayerName,
83 : OGRGeoRSSDataSource* poDS,
84 : OGRSpatialReference *poSRSIn,
85 38 : int bWriteMode)
86 :
87 : {
88 38 : eof = FALSE;
89 38 : nNextFID = 0;
90 :
91 38 : this->poDS = poDS;
92 38 : this->bWriteMode = bWriteMode;
93 :
94 38 : eFormat = poDS->GetFormat();
95 :
96 38 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
97 38 : poFeatureDefn->Reference();
98 :
99 38 : poSRS = poSRSIn;
100 38 : if (poSRS)
101 2 : poSRS->Reference();
102 :
103 38 : nTotalFeatureCount = 0;
104 :
105 38 : ppoFeatureTab = NULL;
106 38 : nFeatureTabIndex = 0;
107 38 : nFeatureTabLength = 0;
108 38 : pszSubElementName = NULL;
109 38 : pszSubElementValue = NULL;
110 38 : nSubElementValueLen = 0;
111 38 : pszGMLSRSName = NULL;
112 38 : pszTagWithSubTag = NULL;
113 38 : bStopParsing = FALSE;
114 38 : bHasReadSchema = FALSE;
115 38 : setOfFoundFields = NULL;
116 38 : poGlobalGeom = NULL;
117 38 : hasFoundLat = FALSE;
118 38 : hasFoundLon = FALSE;
119 :
120 38 : poFeature = NULL;
121 :
122 : #ifdef HAVE_EXPAT
123 38 : oParser = NULL;
124 : #endif
125 :
126 38 : if (bWriteMode == FALSE)
127 : {
128 26 : fpGeoRSS = VSIFOpenL( pszFilename, "r" );
129 26 : if( fpGeoRSS == NULL )
130 : {
131 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszFilename);
132 0 : return;
133 : }
134 : }
135 : else
136 12 : fpGeoRSS = NULL;
137 :
138 38 : ResetReading();
139 0 : }
140 :
141 : /************************************************************************/
142 : /* ~OGRGeoRSSLayer() */
143 : /************************************************************************/
144 :
145 38 : OGRGeoRSSLayer::~OGRGeoRSSLayer()
146 :
147 : {
148 : #ifdef HAVE_EXPAT
149 38 : if (oParser)
150 26 : XML_ParserFree(oParser);
151 : #endif
152 38 : poFeatureDefn->Release();
153 :
154 38 : if( poSRS != NULL )
155 20 : poSRS->Release();
156 :
157 38 : CPLFree(pszSubElementName);
158 38 : CPLFree(pszSubElementValue);
159 38 : CPLFree(pszGMLSRSName);
160 38 : CPLFree(pszTagWithSubTag);
161 38 : if (setOfFoundFields)
162 24 : CPLHashSetDestroy(setOfFoundFields);
163 38 : if (poGlobalGeom)
164 0 : delete poGlobalGeom;
165 :
166 : int i;
167 38 : for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
168 0 : delete ppoFeatureTab[i];
169 38 : CPLFree(ppoFeatureTab);
170 :
171 38 : if (poFeature)
172 0 : delete poFeature;
173 :
174 38 : if (fpGeoRSS)
175 26 : VSIFCloseL( fpGeoRSS );
176 38 : }
177 :
178 :
179 : /************************************************************************/
180 : /* GetLayerDefn() */
181 : /************************************************************************/
182 :
183 34 : OGRFeatureDefn * OGRGeoRSSLayer::GetLayerDefn()
184 : {
185 34 : if (!bHasReadSchema)
186 16 : LoadSchema();
187 :
188 34 : return poFeatureDefn;
189 : }
190 :
191 :
192 :
193 : #ifdef HAVE_EXPAT
194 :
195 552 : static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
196 : const char **ppszAttr)
197 : {
198 552 : ((OGRGeoRSSLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
199 552 : }
200 :
201 552 : static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
202 : {
203 552 : ((OGRGeoRSSLayer*)pUserData)->endElementCbk(pszName);
204 552 : }
205 :
206 1584 : static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
207 : {
208 1584 : ((OGRGeoRSSLayer*)pUserData)->dataHandlerCbk(data, nLen);
209 1584 : }
210 :
211 : #endif
212 :
213 : /************************************************************************/
214 : /* ResetReading() */
215 : /************************************************************************/
216 :
217 38 : void OGRGeoRSSLayer::ResetReading()
218 :
219 : {
220 38 : if (bWriteMode)
221 12 : return;
222 :
223 26 : eof = FALSE;
224 26 : nNextFID = 0;
225 26 : if (fpGeoRSS)
226 : {
227 26 : VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
228 : #ifdef HAVE_EXPAT
229 26 : if (oParser)
230 0 : XML_ParserFree(oParser);
231 :
232 26 : oParser = OGRCreateExpatXMLParser();
233 26 : XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
234 26 : XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
235 26 : XML_SetUserData(oParser, this);
236 : #endif
237 : }
238 26 : bInFeature = FALSE;
239 26 : hasFoundLat = FALSE;
240 26 : hasFoundLon = FALSE;
241 26 : bInSimpleGeometry = FALSE;
242 26 : bInGMLGeometry = FALSE;
243 26 : bInGeoLat = FALSE;
244 26 : bInGeoLong = FALSE;
245 26 : eGeomType = wkbUnknown;
246 26 : CPLFree(pszSubElementName);
247 26 : pszSubElementName = NULL;
248 26 : CPLFree(pszSubElementValue);
249 26 : pszSubElementValue = NULL;
250 26 : nSubElementValueLen = 0;
251 26 : CPLFree(pszGMLSRSName);
252 26 : pszGMLSRSName = NULL;
253 :
254 26 : if (setOfFoundFields)
255 0 : CPLHashSetDestroy(setOfFoundFields);
256 26 : setOfFoundFields = NULL;
257 :
258 : int i;
259 26 : for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
260 0 : delete ppoFeatureTab[i];
261 26 : CPLFree(ppoFeatureTab);
262 26 : nFeatureTabIndex = 0;
263 26 : nFeatureTabLength = 0;
264 26 : ppoFeatureTab = NULL;
265 26 : if (poFeature)
266 0 : delete poFeature;
267 26 : poFeature = NULL;
268 :
269 26 : currentDepth = 0;
270 26 : featureDepth = 0;
271 26 : geometryDepth = 0;
272 26 : bInTagWithSubTag = FALSE;
273 26 : CPLFree(pszTagWithSubTag);
274 26 : pszTagWithSubTag = NULL;
275 : }
276 :
277 : #ifdef HAVE_EXPAT
278 :
279 : /************************************************************************/
280 : /* AddStrToSubElementValue() */
281 : /************************************************************************/
282 :
283 376 : void OGRGeoRSSLayer::AddStrToSubElementValue(const char* pszStr)
284 : {
285 376 : int len = strlen(pszStr);
286 : char* pszNewSubElementValue = (char*)
287 376 : VSIRealloc(pszSubElementValue, nSubElementValueLen + len + 1);
288 376 : 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 376 : pszSubElementValue = pszNewSubElementValue;
296 :
297 376 : memcpy(pszSubElementValue + nSubElementValueLen, pszStr, len);
298 376 : nSubElementValueLen += len;
299 : }
300 :
301 : /************************************************************************/
302 : /* OGRGeoRSS_GetOGRCompatibleTagName() */
303 : /************************************************************************/
304 :
305 : /** Replace ':' from XML NS element name by '_' more OGR friendly */
306 624 : static char* OGRGeoRSS_GetOGRCompatibleTagName(const char* pszName)
307 : {
308 624 : char* pszModName = CPLStrdup(pszName);
309 : int i;
310 5424 : for(i=0;pszModName[i] != 0;i++)
311 : {
312 4800 : if (pszModName[i] == ':')
313 48 : pszModName[i] = '_';
314 : }
315 624 : return pszModName;
316 : }
317 :
318 : /************************************************************************/
319 : /* OGRGeoRSSLayerATOMTagHasSubElement() */
320 : /************************************************************************/
321 :
322 160 : static int OGRGeoRSSLayerATOMTagHasSubElement(const char* pszName)
323 : {
324 : unsigned int i;
325 416 : for(i=0;apszAllowedATOMFieldNamesWithSubElements[i] != NULL;i++)
326 : {
327 304 : if (strcmp(pszName, apszAllowedATOMFieldNamesWithSubElements[i]) == 0)
328 48 : return TRUE;
329 : }
330 112 : return FALSE;
331 : }
332 :
333 : /************************************************************************/
334 : /* startElementCbk() */
335 : /************************************************************************/
336 :
337 552 : void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
338 : {
339 552 : int bSerializeTag = FALSE;
340 :
341 552 : if (bStopParsing) return;
342 :
343 606 : 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 54 : featureDepth = currentDepth;
347 :
348 54 : if (poFeature)
349 0 : delete poFeature;
350 :
351 54 : poFeature = new OGRFeature( poFeatureDefn );
352 54 : poFeature->SetFID( nNextFID++ );
353 :
354 54 : bInFeature = TRUE;
355 54 : hasFoundLat = FALSE;
356 54 : hasFoundLon = FALSE;
357 54 : bInSimpleGeometry = FALSE;
358 54 : bInGMLGeometry = FALSE;
359 54 : bInGeoLat = FALSE;
360 54 : bInGeoLong = FALSE;
361 54 : eGeomType = wkbUnknown;
362 54 : geometryDepth = 0;
363 54 : bInTagWithSubTag = FALSE;
364 :
365 54 : if (setOfFoundFields)
366 30 : CPLHashSetDestroy(setOfFoundFields);
367 54 : setOfFoundFields = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
368 : }
369 518 : else if (bInFeature && bInTagWithSubTag && currentDepth == 3)
370 : {
371 20 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszName));
372 :
373 20 : CPLFree(pszSubElementName);
374 20 : pszSubElementName = NULL;
375 20 : CPLFree(pszSubElementValue);
376 20 : pszSubElementValue = NULL;
377 20 : nSubElementValueLen = 0;
378 :
379 20 : iCurrentField = poFeatureDefn->GetFieldIndex(pszFieldName);
380 20 : if (iCurrentField >= 0)
381 20 : pszSubElementName = CPLStrdup(pszFieldName);
382 :
383 20 : CPLFree(pszFieldName);
384 : }
385 478 : else if (bInFeature && eFormat == GEORSS_ATOM &&
386 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
387 : {
388 12 : CPLFree(pszTagWithSubTag);
389 12 : pszTagWithSubTag = CPLStrdup(pszName);
390 :
391 12 : int count = 1;
392 28 : while(CPLHashSetLookup(setOfFoundFields, pszTagWithSubTag) != NULL)
393 : {
394 4 : count ++;
395 4 : CPLFree(pszTagWithSubTag);
396 4 : pszTagWithSubTag = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
397 : }
398 12 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
399 :
400 12 : bInTagWithSubTag = TRUE;
401 : }
402 466 : else if (bInGMLGeometry)
403 : {
404 34 : bSerializeTag = TRUE;
405 : }
406 432 : else if (bInSimpleGeometry || bInGeoLat || bInGeoLong)
407 : {
408 : /* Shouldn't happen for a valid document */
409 : }
410 434 : else if (IS_LAT_ELEMENT(pszName))
411 : {
412 2 : CPLFree(pszSubElementValue);
413 2 : pszSubElementValue = NULL;
414 2 : nSubElementValueLen = 0;
415 2 : bInGeoLat = TRUE;
416 : }
417 432 : else if (IS_LON_ELEMENT(pszName))
418 : {
419 2 : CPLFree(pszSubElementValue);
420 2 : pszSubElementValue = NULL;
421 2 : nSubElementValueLen = 0;
422 2 : bInGeoLong = TRUE;
423 : }
424 448 : 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 20 : CPLFree(pszSubElementValue);
431 20 : pszSubElementValue = NULL;
432 20 : 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 20 : wkbUnknown;
439 20 : bInSimpleGeometry = TRUE;
440 20 : geometryDepth = currentDepth;
441 : }
442 428 : 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 20 : CPLFree(pszSubElementValue);
451 20 : pszSubElementValue = NULL;
452 20 : nSubElementValueLen = 0;
453 20 : AddStrToSubElementValue(CPLSPrintf("<%s>", pszName));
454 20 : bInGMLGeometry = TRUE;
455 20 : geometryDepth = currentDepth;
456 20 : CPLFree(pszGMLSRSName);
457 20 : pszGMLSRSName = NULL;
458 22 : for (int i = 0; ppszAttr[i]; i += 2)
459 : {
460 2 : if (strcmp(ppszAttr[i], "srsName") == 0)
461 : {
462 2 : if (pszGMLSRSName == NULL)
463 2 : pszGMLSRSName = CPLStrdup(ppszAttr[i+1]);
464 : }
465 : }
466 : }
467 648 : else if (bInFeature && currentDepth == featureDepth + 1)
468 : {
469 260 : CPLFree(pszSubElementName);
470 260 : pszSubElementName = NULL;
471 260 : CPLFree(pszSubElementValue);
472 260 : pszSubElementValue = NULL;
473 260 : nSubElementValueLen = 0;
474 260 : iCurrentField = -1;
475 :
476 260 : pszSubElementName = CPLStrdup(pszName);
477 260 : int count = 1;
478 534 : while(CPLHashSetLookup(setOfFoundFields, pszSubElementName) != NULL)
479 : {
480 14 : count ++;
481 14 : CPLFree(pszSubElementName);
482 14 : pszSubElementName = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
483 : }
484 260 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszSubElementName));
485 :
486 260 : char* pszCompatibleName = OGRGeoRSS_GetOGRCompatibleTagName(pszSubElementName);
487 260 : iCurrentField = poFeatureDefn->GetFieldIndex(pszCompatibleName);
488 260 : CPLFree(pszSubElementName);
489 :
490 322 : for(int i = 0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL; i+=2)
491 : {
492 : char* pszAttrCompatibleName =
493 62 : OGRGeoRSS_GetOGRCompatibleTagName(CPLSPrintf("%s_%s", pszCompatibleName, ppszAttr[i]));
494 62 : int iAttrField = poFeatureDefn->GetFieldIndex(pszAttrCompatibleName);
495 62 : if (iAttrField >= 0)
496 : {
497 62 : if (poFeatureDefn->GetFieldDefn(iAttrField)->GetType() == OFTReal)
498 0 : poFeature->SetField( iAttrField, CPLAtof(ppszAttr[i+1]) );
499 : else
500 62 : poFeature->SetField( iAttrField, ppszAttr[i+1] );
501 : }
502 62 : CPLFree(pszAttrCompatibleName);
503 : }
504 :
505 260 : if (iCurrentField < 0)
506 : {
507 28 : pszSubElementName = NULL;
508 : }
509 : else
510 : {
511 232 : pszSubElementName = CPLStrdup(pszCompatibleName);
512 : }
513 260 : CPLFree(pszCompatibleName);
514 : }
515 128 : else if (bInFeature && currentDepth > featureDepth + 1 && pszSubElementName != NULL)
516 : {
517 12 : bSerializeTag = TRUE;
518 : }
519 :
520 552 : if (bSerializeTag)
521 : {
522 46 : AddStrToSubElementValue("<");
523 46 : AddStrToSubElementValue(pszName);
524 50 : for(int i = 0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL; i+=2)
525 : {
526 4 : AddStrToSubElementValue(" ");
527 4 : AddStrToSubElementValue(ppszAttr[i]);
528 4 : AddStrToSubElementValue("=\"");
529 4 : AddStrToSubElementValue(ppszAttr[i+1]);
530 4 : AddStrToSubElementValue("\"");
531 : }
532 46 : AddStrToSubElementValue(">");
533 : }
534 :
535 552 : currentDepth++;
536 : }
537 :
538 : /************************************************************************/
539 : /* OGRGeoRSS_GetGMLEnvelope() */
540 : /************************************************************************/
541 :
542 2 : static OGRGeometry* OGRGeoRSS_GetGMLEnvelope(const char* pszGML)
543 : {
544 2 : OGRGeometry* poGeom = NULL;
545 2 : CPLXMLNode* poNode = CPLParseXMLString(pszGML);
546 2 : const char* pszLowerCorner = CPLGetXMLValue(poNode, "gml:lowerCorner", NULL);
547 2 : const char* pszUpperCorner = CPLGetXMLValue(poNode, "gml:upperCorner", NULL);
548 2 : if (pszLowerCorner && pszUpperCorner)
549 : {
550 : char **papszTokensLower;
551 : char **papszTokensUpper;
552 :
553 : papszTokensLower = CSLTokenizeStringComplex(
554 2 : pszLowerCorner, " ,", FALSE, FALSE );
555 : papszTokensUpper = CSLTokenizeStringComplex(
556 2 : pszUpperCorner, " ,", FALSE, FALSE );
557 2 : if (CSLCount(papszTokensLower) == 2 &&
558 : CSLCount(papszTokensUpper) == 2)
559 : {
560 2 : OGRPolygon* poPolygon = new OGRPolygon();
561 4 : OGRLinearRing* poLinearRing = new OGRLinearRing();
562 2 : poPolygon->addRingDirectly(poLinearRing);
563 2 : double x1 = CPLAtof(papszTokensLower[0]);
564 2 : double y1 = CPLAtof(papszTokensLower[1]);
565 2 : double x2 = CPLAtof(papszTokensUpper[0]);
566 2 : double y2 = CPLAtof(papszTokensUpper[1]);
567 2 : poLinearRing->addPoint( x1, y1 );
568 2 : poLinearRing->addPoint( x2, y1 );
569 2 : poLinearRing->addPoint( x2, y2 );
570 2 : poLinearRing->addPoint( x1, y2 );
571 2 : poLinearRing->addPoint( x1, y1 );
572 :
573 2 : poGeom = poPolygon;
574 : }
575 :
576 2 : CSLDestroy(papszTokensLower);
577 2 : CSLDestroy(papszTokensUpper);
578 : }
579 2 : CPLDestroyXMLNode(poNode);
580 2 : return poGeom;
581 : }
582 :
583 :
584 : /************************************************************************/
585 : /* OGRGeoRSSLayerTrimLeadingAndTrailingSpaces() */
586 : /************************************************************************/
587 :
588 20 : static void OGRGeoRSSLayerTrimLeadingAndTrailingSpaces(char* pszStr)
589 : {
590 : int i;
591 :
592 : /* Trim leading spaces, tabs and newlines */
593 20 : i = 0;
594 124 : while(pszStr[i] != '\0' &&
595 78 : (pszStr[i] == ' ' || pszStr[i] == '\t' || pszStr[i] == '\n'))
596 6 : i ++;
597 20 : memmove(pszStr, pszStr + i, strlen(pszStr + i) + 1);
598 :
599 : /* Trim trailing spaces, tabs and newlines */
600 20 : i = strlen(pszStr) - 1;
601 112 : while(i >= 0 &&
602 66 : (pszStr[i] == ' ' || pszStr[i] == '\t' || pszStr[i] == '\n'))
603 : {
604 6 : pszStr[i] = '\0';
605 6 : i --;
606 : }
607 20 : }
608 :
609 : /************************************************************************/
610 : /* endElementCbk() */
611 : /************************************************************************/
612 :
613 552 : void OGRGeoRSSLayer::endElementCbk(const char *pszName)
614 : {
615 552 : OGRGeometry* poGeom = NULL;
616 :
617 552 : if (bStopParsing) return;
618 :
619 552 : currentDepth--;
620 :
621 552 : 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 54 : bInFeature = FALSE;
625 54 : bInTagWithSubTag = FALSE;
626 :
627 56 : if (hasFoundLat && hasFoundLon)
628 2 : poFeature->SetGeometryDirectly( new OGRPoint( lonVal, latVal ) );
629 52 : else if (poFeature->GetGeometryRef() == NULL && poGlobalGeom != NULL)
630 0 : poFeature->SetGeometry(poGlobalGeom);
631 :
632 54 : hasFoundLat = FALSE;
633 54 : hasFoundLon = FALSE;
634 :
635 54 : if (poSRS != NULL && poFeature->GetGeometryRef() != NULL)
636 38 : poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
637 :
638 54 : 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 54 : sizeof(OGRFeature*) * (nFeatureTabLength + 1));
646 54 : ppoFeatureTab[nFeatureTabLength] = poFeature;
647 54 : nFeatureTabLength++;
648 : }
649 : else
650 : {
651 0 : delete poFeature;
652 : }
653 54 : poFeature = NULL;
654 54 : return;
655 : }
656 :
657 518 : if (bInTagWithSubTag && currentDepth == 3)
658 : {
659 20 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszName));
660 :
661 20 : if (iCurrentField != -1 && pszSubElementName &&
662 : strcmp(pszFieldName, pszSubElementName) == 0 && poFeature &&
663 : pszSubElementValue && nSubElementValueLen)
664 : {
665 20 : pszSubElementValue[nSubElementValueLen] = 0;
666 20 : if (poFeatureDefn->GetFieldDefn(iCurrentField)->GetType() == OFTReal)
667 0 : poFeature->SetField( iCurrentField, CPLAtof(pszSubElementValue) );
668 : else
669 20 : poFeature->SetField( iCurrentField, pszSubElementValue);
670 : }
671 :
672 20 : CPLFree(pszSubElementName);
673 20 : pszSubElementName = NULL;
674 20 : CPLFree(pszSubElementValue);
675 20 : pszSubElementValue = NULL;
676 20 : nSubElementValueLen = 0;
677 :
678 20 : CPLFree(pszFieldName);
679 : }
680 478 : else if (bInFeature && eFormat == GEORSS_ATOM &&
681 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
682 : {
683 12 : bInTagWithSubTag = FALSE;
684 : }
685 466 : else if (bInGMLGeometry)
686 : {
687 54 : AddStrToSubElementValue("</");
688 54 : AddStrToSubElementValue(pszName);
689 54 : AddStrToSubElementValue(">");
690 54 : if (currentDepth > geometryDepth)
691 : {
692 : }
693 : else
694 : {
695 20 : pszSubElementValue[nSubElementValueLen] = 0;
696 20 : CPLAssert(strncmp(pszName, "gml:", 4) == 0);
697 20 : if (strcmp(pszName, "gml:Envelope") == 0)
698 2 : poGeom = OGRGeoRSS_GetGMLEnvelope(pszSubElementValue);
699 : else
700 18 : poGeom = (OGRGeometry*) OGR_G_CreateFromGML(pszSubElementValue);
701 :
702 20 : if (poGeom != NULL && !poGeom->IsEmpty() )
703 : {
704 18 : int bSwapCoordinates = FALSE;
705 18 : if (pszGMLSRSName)
706 : {
707 2 : OGRSpatialReference* poSRSFeature = new OGRSpatialReference();
708 2 : poSRSFeature->importFromURN(pszGMLSRSName);
709 2 : poGeom->assignSpatialReference(poSRSFeature);
710 2 : poSRSFeature->Release();
711 : }
712 : else
713 16 : bSwapCoordinates = TRUE; /* lat, lon WGS 84 */
714 :
715 18 : if (bSwapCoordinates)
716 : {
717 16 : poGeom->swapXY();
718 : }
719 : }
720 20 : bInGMLGeometry = FALSE;
721 : }
722 : }
723 412 : else if (bInSimpleGeometry)
724 : {
725 20 : if (currentDepth > geometryDepth)
726 : {
727 : /* Shouldn't happen for a valid document */
728 : }
729 : else
730 : {
731 20 : if (pszSubElementValue)
732 : {
733 20 : pszSubElementValue[nSubElementValueLen] = 0;
734 :
735 : /* Trim any leading and trailing spaces, tabs, newlines, etc... */
736 20 : OGRGeoRSSLayerTrimLeadingAndTrailingSpaces(pszSubElementValue);
737 :
738 : /* Caution : Order is latitude, longitude */
739 : char** papszTokens =
740 : CSLTokenizeStringComplex( pszSubElementValue,
741 20 : " ,", TRUE, FALSE );
742 :
743 20 : int nTokens = CSLCount(papszTokens);
744 22 : 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 2 : pszSubElementValue);
753 : }
754 18 : else if (eGeomType == wkbPoint)
755 : {
756 6 : poGeom = new OGRPoint( CPLAtof(papszTokens[1]),
757 12 : CPLAtof(papszTokens[0]) );
758 : }
759 12 : else if (eGeomType == wkbLineString)
760 : {
761 4 : OGRLineString* poLineString = new OGRLineString ();
762 4 : poGeom = poLineString;
763 : int i;
764 16 : for(i=0;i<nTokens;i+=2)
765 : {
766 12 : poLineString->addPoint( CPLAtof(papszTokens[i+1]),
767 24 : CPLAtof(papszTokens[i]) );
768 : }
769 : }
770 8 : else if (eGeomType == wkbPolygon)
771 : {
772 8 : OGRPolygon* poPolygon = new OGRPolygon();
773 16 : OGRLinearRing* poLinearRing = new OGRLinearRing();
774 8 : poGeom = poPolygon;
775 8 : poPolygon->addRingDirectly(poLinearRing);
776 8 : if (strcmp(pszName, "georss:polygon") == 0)
777 : {
778 : int i;
779 36 : for(i=0;i<nTokens;i+=2)
780 : {
781 30 : poLinearRing->addPoint( CPLAtof(papszTokens[i+1]),
782 60 : CPLAtof(papszTokens[i]) );
783 : }
784 : }
785 : else
786 : {
787 2 : double lat1 = CPLAtof(papszTokens[0]);
788 2 : double lon1 = CPLAtof(papszTokens[1]);
789 2 : double lat2 = CPLAtof(papszTokens[2]);
790 2 : double lon2 = CPLAtof(papszTokens[3]);
791 2 : poLinearRing->addPoint( lon1, lat1 );
792 2 : poLinearRing->addPoint( lon1, lat2 );
793 2 : poLinearRing->addPoint( lon2, lat2 );
794 2 : poLinearRing->addPoint( lon2, lat1 );
795 2 : poLinearRing->addPoint( lon1, lat1 );
796 : }
797 : }
798 :
799 20 : CSLDestroy(papszTokens);
800 : }
801 20 : bInSimpleGeometry = FALSE;
802 : }
803 : }
804 394 : else if (IS_LAT_ELEMENT(pszName))
805 : {
806 2 : if (pszSubElementValue)
807 : {
808 2 : hasFoundLat = TRUE;
809 2 : pszSubElementValue[nSubElementValueLen] = 0;
810 2 : latVal = CPLAtof(pszSubElementValue);
811 : }
812 2 : bInGeoLat = FALSE;
813 : }
814 392 : else if (IS_LON_ELEMENT(pszName))
815 : {
816 2 : if (pszSubElementValue)
817 : {
818 2 : hasFoundLon = TRUE;
819 2 : pszSubElementValue[nSubElementValueLen] = 0;
820 2 : lonVal = CPLAtof(pszSubElementValue);
821 : }
822 2 : bInGeoLong = FALSE;
823 : }
824 648 : else if (bInFeature && currentDepth == featureDepth + 1)
825 : {
826 260 : if (iCurrentField != -1 && pszSubElementName &&
827 : poFeature && pszSubElementValue && nSubElementValueLen)
828 : {
829 232 : pszSubElementValue[nSubElementValueLen] = 0;
830 232 : if (poFeatureDefn->GetFieldDefn(iCurrentField)->GetType() == OFTDateTime)
831 : {
832 : int year, month, day, hour, minute, TZ;
833 : int nsecond;
834 : float fsecond;
835 50 : if (OGRParseRFC822DateTime(pszSubElementValue, &year, &month, &day,
836 : &hour, &minute, &nsecond, &TZ))
837 : {
838 : poFeature->SetField(iCurrentField, year, month, day,
839 42 : hour, minute, nsecond, TZ);
840 : }
841 8 : else if (OGRParseXMLDateTime(pszSubElementValue, &year, &month, &day,
842 : &hour, &minute, &fsecond, &TZ))
843 : {
844 : poFeature->SetField(iCurrentField, year, month, day,
845 8 : 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 182 : if (poFeatureDefn->GetFieldDefn(iCurrentField)->GetType() == OFTReal)
856 0 : poFeature->SetField( iCurrentField, CPLAtof(pszSubElementValue) );
857 : else
858 182 : poFeature->SetField( iCurrentField, pszSubElementValue);
859 : }
860 : }
861 :
862 260 : CPLFree(pszSubElementName);
863 260 : pszSubElementName = NULL;
864 260 : CPLFree(pszSubElementValue);
865 260 : pszSubElementValue = NULL;
866 260 : nSubElementValueLen = 0;
867 : }
868 128 : else if (bInFeature && currentDepth > featureDepth + 1 && pszSubElementName != NULL)
869 : {
870 12 : AddStrToSubElementValue("</");
871 12 : AddStrToSubElementValue(pszName);
872 12 : AddStrToSubElementValue(">");
873 : }
874 :
875 498 : if (poGeom != NULL)
876 : {
877 36 : if (poFeature != NULL)
878 : {
879 36 : 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 462 : 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 1584 : void OGRGeoRSSLayer::dataHandlerCbk(const char *data, int nLen)
904 : {
905 1584 : if (bStopParsing) return;
906 :
907 1584 : if (bInGMLGeometry == TRUE || bInSimpleGeometry == TRUE ||
908 : bInGeoLat == TRUE || bInGeoLong == TRUE ||
909 : pszSubElementName != NULL)
910 : {
911 : char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
912 380 : nSubElementValueLen + nLen + 1);
913 380 : 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 380 : pszSubElementValue = pszNewSubElementValue;
921 380 : memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
922 380 : nSubElementValueLen += nLen;
923 : }
924 : }
925 : #endif
926 :
927 : /************************************************************************/
928 : /* GetNextFeature() */
929 : /************************************************************************/
930 :
931 54 : OGRFeature *OGRGeoRSSLayer::GetNextFeature()
932 : {
933 54 : 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 54 : if (fpGeoRSS == NULL)
941 0 : return NULL;
942 :
943 54 : if (!bHasReadSchema)
944 8 : LoadSchema();
945 :
946 54 : if (bStopParsing)
947 0 : return NULL;
948 :
949 : #ifdef HAVE_EXPAT
950 54 : if (nFeatureTabIndex < nFeatureTabLength)
951 : {
952 30 : return ppoFeatureTab[nFeatureTabIndex++];
953 : }
954 :
955 24 : if (VSIFEofL(fpGeoRSS))
956 0 : return NULL;
957 :
958 : char aBuf[BUFSIZ];
959 :
960 24 : CPLFree(ppoFeatureTab);
961 24 : ppoFeatureTab = NULL;
962 24 : nFeatureTabLength = 0;
963 24 : nFeatureTabIndex = 0;
964 :
965 : int nDone;
966 24 : do
967 : {
968 : unsigned int nLen =
969 24 : (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGeoRSS );
970 24 : nDone = VSIFEofL(fpGeoRSS);
971 24 : 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 24 : return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
984 : #else
985 : return NULL;
986 : #endif
987 : }
988 :
989 : /************************************************************************/
990 : /* GetSpatialRef() */
991 : /************************************************************************/
992 :
993 40 : OGRSpatialReference *OGRGeoRSSLayer::GetSpatialRef()
994 :
995 : {
996 40 : if (!bWriteMode && !bHasReadSchema)
997 12 : LoadSchema();
998 :
999 40 : return poSRS;
1000 : }
1001 :
1002 : /************************************************************************/
1003 : /* OGRGeoRSSLayerIsStandardFieldInternal() */
1004 : /************************************************************************/
1005 :
1006 182 : static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
1007 : const char** papszNames)
1008 : {
1009 : unsigned int i;
1010 1374 : for( i = 0; papszNames[i] != NULL; i++)
1011 : {
1012 1362 : if (strcmp(pszName, papszNames[i]) == 0)
1013 : {
1014 148 : return TRUE;
1015 : }
1016 :
1017 1214 : const char* pszUnderscore = strchr(papszNames[i], '_');
1018 1214 : if (pszUnderscore == NULL)
1019 : {
1020 502 : int nLen = strlen(papszNames[i]);
1021 502 : if (strncmp(pszName, papszNames[i], nLen) == 0)
1022 : {
1023 24 : int k = nLen;
1024 60 : while(pszName[k] >= '0' && pszName[k] <= '9')
1025 12 : k++;
1026 24 : if (pszName[k] == '\0')
1027 6 : return TRUE;
1028 : }
1029 : }
1030 : else
1031 : {
1032 712 : int nLen = pszUnderscore - papszNames[i];
1033 712 : if (strncmp(pszName, papszNames[i], nLen) == 0)
1034 : {
1035 46 : int k = nLen;
1036 120 : while(pszName[k] >= '0' && pszName[k] <= '9')
1037 28 : k++;
1038 46 : if (pszName[k] == '_' && strcmp(pszName + k, pszUnderscore) == 0)
1039 16 : return TRUE;
1040 : }
1041 : }
1042 : }
1043 12 : return FALSE;
1044 : }
1045 :
1046 : /************************************************************************/
1047 : /* OGRGeoRSSLayer::IsStandardField() */
1048 : /************************************************************************/
1049 :
1050 182 : int OGRGeoRSSLayer::IsStandardField(const char* pszName)
1051 : {
1052 182 : if (eFormat == GEORSS_RSS)
1053 : {
1054 : return OGRGeoRSSLayerIsStandardFieldInternal(pszName,
1055 138 : apszAllowedRSSFieldNames);
1056 : }
1057 : else
1058 : {
1059 : return OGRGeoRSSLayerIsStandardFieldInternal(pszName,
1060 44 : apszAllowedATOMFieldNames);
1061 : }
1062 : }
1063 :
1064 : /************************************************************************/
1065 : /* OGRGeoRSSLayerSplitComposedField() */
1066 : /************************************************************************/
1067 :
1068 206 : static void OGRGeoRSSLayerSplitComposedField(const char* pszName,
1069 : char** ppszElementName,
1070 : char** ppszNumber,
1071 : char** ppszAttributeName)
1072 : {
1073 206 : *ppszElementName = CPLStrdup(pszName);
1074 :
1075 206 : int i = 0;
1076 4360 : while(pszName[i] != '\0' && pszName[i] != '_' &&
1077 2652 : !(pszName[i] >= '0' && pszName[i] <= '9'))
1078 : {
1079 1296 : i++;
1080 : }
1081 :
1082 206 : (*ppszElementName)[i] = '\0';
1083 :
1084 236 : if (pszName[i] >= '0' && pszName[i] <= '9')
1085 : {
1086 30 : *ppszNumber = CPLStrdup(pszName + i);
1087 30 : char* pszUnderscore = strchr(*ppszNumber, '_');
1088 30 : if (pszUnderscore)
1089 : {
1090 22 : *pszUnderscore = '\0';
1091 22 : *ppszAttributeName = CPLStrdup(pszUnderscore + 1);
1092 : }
1093 : else
1094 : {
1095 8 : *ppszAttributeName = NULL;
1096 : }
1097 : }
1098 : else
1099 : {
1100 176 : *ppszNumber = CPLStrdup("");
1101 176 : if (pszName[i] == '_')
1102 : {
1103 58 : *ppszAttributeName = CPLStrdup(pszName + i + 1);
1104 : }
1105 : else
1106 : {
1107 118 : *ppszAttributeName = NULL;
1108 : }
1109 : }
1110 206 : }
1111 :
1112 : /************************************************************************/
1113 : /* OGRGeoRSSLayerWriteSimpleElement() */
1114 : /************************************************************************/
1115 :
1116 16 : 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 16 : VSIFPrintfL(fp, " <%s", pszElementName);
1124 :
1125 : unsigned k;
1126 304 : for( k = 0; papszNames[k] != NULL ; k++)
1127 : {
1128 368 : if (strncmp(papszNames[k], pszElementName, strlen(pszElementName)) == 0 &&
1129 80 : papszNames[k][strlen(pszElementName)] == '_')
1130 : {
1131 28 : const char* pszAttributeName = papszNames[k] + strlen(pszElementName) + 1;
1132 28 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s%s_%s", pszElementName, pszNumber, pszAttributeName));
1133 28 : int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1134 28 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1135 : {
1136 : char* pszValue =
1137 26 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1138 26 : if (poFeatureDefn->GetFieldDefn(iIndex)->GetType() == OFTReal)
1139 : {
1140 0 : char* pszComma = strchr(pszValue, ',');
1141 0 : if (pszComma)
1142 0 : *pszComma = '.';
1143 : }
1144 26 : VSIFPrintfL(fp, " %s=\"%s\"", pszAttributeName, pszValue);
1145 26 : CPLFree(pszValue);
1146 : }
1147 28 : CPLFree(pszFieldName);
1148 : }
1149 : }
1150 :
1151 16 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s%s", pszElementName, pszNumber));
1152 16 : int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1153 16 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1154 : {
1155 12 : VSIFPrintfL(fp, ">");
1156 :
1157 : char* pszValue =
1158 12 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1159 12 : if (poFeatureDefn->GetFieldDefn(iIndex)->GetType() == OFTReal)
1160 : {
1161 0 : char* pszComma = strchr(pszValue, ',');
1162 0 : if (pszComma)
1163 0 : *pszComma = '.';
1164 : }
1165 12 : VSIFPrintfL(fp, "%s", pszValue);
1166 12 : CPLFree(pszValue);
1167 :
1168 12 : VSIFPrintfL(fp, "</%s>\n", pszElementName);
1169 : }
1170 : else
1171 : {
1172 4 : VSIFPrintfL(fp, "/>\n");
1173 : }
1174 16 : CPLFree(pszFieldName);
1175 16 : }
1176 :
1177 : /************************************************************************/
1178 : /* CreateFeature() */
1179 : /************************************************************************/
1180 :
1181 30 : OGRErr OGRGeoRSSLayer::CreateFeature( OGRFeature *poFeature )
1182 :
1183 : {
1184 30 : VSILFILE* fp = poDS->GetOutputFP();
1185 30 : if (fp == NULL)
1186 0 : return CE_Failure;
1187 :
1188 30 : nNextFID ++;
1189 :
1190 : /* Verify that compulsory feeds are set. Otherwise put some default value in them */
1191 30 : if (eFormat == GEORSS_RSS)
1192 : {
1193 28 : int iFieldTitle = poFeatureDefn->GetFieldIndex( "title" );
1194 28 : int iFieldDescription = poFeatureDefn->GetFieldIndex( "description" );
1195 :
1196 28 : VSIFPrintfL(fp, " <item>\n");
1197 :
1198 28 : if ((iFieldTitle == -1 || poFeature->IsFieldSet( iFieldTitle ) == FALSE) &&
1199 : (iFieldDescription == -1 || poFeature->IsFieldSet( iFieldDescription ) == FALSE))
1200 : {
1201 4 : VSIFPrintfL(fp, " <title>Feature %d</title>\n", nNextFID);
1202 : }
1203 : }
1204 : else
1205 : {
1206 2 : VSIFPrintfL(fp, " <entry>\n");
1207 :
1208 2 : int iFieldId = poFeatureDefn->GetFieldIndex( "id" );
1209 2 : int iFieldTitle = poFeatureDefn->GetFieldIndex( "title" );
1210 2 : int iFieldUpdated = poFeatureDefn->GetFieldIndex( "updated" );
1211 :
1212 2 : if (iFieldId == -1 || poFeature->IsFieldSet( iFieldId ) == FALSE)
1213 : {
1214 0 : VSIFPrintfL(fp, " <id>Feature %d</id>\n", nNextFID);
1215 : }
1216 :
1217 2 : if (iFieldTitle == -1 || poFeature->IsFieldSet( iFieldTitle ) == FALSE)
1218 : {
1219 0 : VSIFPrintfL(fp, " <title>Title for feature %d</title>\n", nNextFID);
1220 : }
1221 :
1222 2 : if (iFieldUpdated == -1 || poFeature->IsFieldSet(iFieldUpdated ) == FALSE)
1223 : {
1224 0 : VSIFPrintfL(fp, " <updated>2009-01-01T00:00:00Z</updated>\n");
1225 : }
1226 : }
1227 :
1228 30 : int nFieldCount = poFeatureDefn->GetFieldCount();
1229 30 : int* pbUsed = (int*)CPLCalloc(sizeof(int), nFieldCount);
1230 :
1231 292 : for(int i = 0; i < nFieldCount; i ++)
1232 : {
1233 262 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
1234 262 : const char* pszName = poFieldDefn->GetNameRef();
1235 :
1236 262 : if ( ! poFeature->IsFieldSet( i ) )
1237 96 : continue;
1238 :
1239 : char* pszElementName;
1240 : char* pszNumber;
1241 : char* pszAttributeName;
1242 166 : OGRGeoRSSLayerSplitComposedField(pszName, &pszElementName, &pszNumber, &pszAttributeName);
1243 :
1244 166 : int bWillSkip = FALSE;
1245 : /* Handle Atom entries with elements with sub-elements like */
1246 : /* <author><name>...</name><uri>...</uri></author */
1247 166 : if (eFormat == GEORSS_ATOM)
1248 : {
1249 : unsigned int k;
1250 104 : for (k=0;apszAllowedATOMFieldNamesWithSubElements[k] != NULL;k++)
1251 : {
1252 74 : if (strcmp(pszElementName, apszAllowedATOMFieldNamesWithSubElements[k]) == 0 &&
1253 : pszAttributeName != NULL)
1254 : {
1255 10 : bWillSkip = TRUE;
1256 10 : if (pbUsed[i])
1257 4 : break;
1258 :
1259 6 : VSIFPrintfL(fp, " <%s>\n", pszElementName);
1260 :
1261 : int j;
1262 46 : for(j = i; j < nFieldCount; j ++)
1263 : {
1264 40 : poFieldDefn = poFeatureDefn->GetFieldDefn( j );
1265 40 : if ( ! poFeature->IsFieldSet( j ) )
1266 0 : continue;
1267 :
1268 : char* pszElementName2;
1269 : char* pszNumber2;
1270 : char* pszAttributeName2;
1271 : OGRGeoRSSLayerSplitComposedField(poFieldDefn->GetNameRef(),
1272 40 : &pszElementName2, &pszNumber2, &pszAttributeName2);
1273 :
1274 40 : if (strcmp(pszElementName2, pszElementName) == 0 &&
1275 : strcmp(pszNumber, pszNumber2) == 0 && pszAttributeName2 != NULL)
1276 : {
1277 10 : pbUsed[j] = TRUE;
1278 :
1279 : char* pszValue =
1280 10 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( j ));
1281 10 : if (poFeatureDefn->GetFieldDefn(j)->GetType() == OFTReal)
1282 : {
1283 0 : char* pszComma = strchr(pszValue, ',');
1284 0 : if (pszComma)
1285 0 : *pszComma = '.';
1286 : }
1287 10 : VSIFPrintfL(fp, " <%s>%s</%s>\n", pszAttributeName2, pszValue, pszAttributeName2);
1288 10 : CPLFree(pszValue);
1289 : }
1290 40 : CPLFree(pszElementName2);
1291 40 : CPLFree(pszNumber2);
1292 40 : CPLFree(pszAttributeName2);
1293 : }
1294 :
1295 6 : VSIFPrintfL(fp, " </%s>\n", pszElementName);
1296 :
1297 6 : break;
1298 : }
1299 : }
1300 : }
1301 :
1302 166 : if (bWillSkip)
1303 : {
1304 : /* Do nothing */
1305 : }
1306 180 : else if (eFormat == GEORSS_RSS &&
1307 : strcmp(pszName, "pubDate") == 0)
1308 : {
1309 : int year, month, day, hour, minute, second, TZFlag;
1310 24 : if (poFeature->GetFieldAsDateTime(i, &year, &month, &day,
1311 : &hour, &minute, &second, &TZFlag))
1312 : {
1313 24 : char* pszDate = OGRGetRFC822DateTime(year, month, day, hour, minute, second, TZFlag);
1314 : VSIFPrintfL(fp, " <%s>%s</%s>\n",
1315 24 : pszName, pszDate, pszName);
1316 24 : CPLFree(pszDate);
1317 : }
1318 : }
1319 136 : 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 4 : if (poFeature->GetFieldAsDateTime(i, &year, &month, &day,
1324 : &hour, &minute, &second, &TZFlag))
1325 : {
1326 4 : char* pszDate = OGRGetXMLDateTime(year, month, day, hour, minute, second, TZFlag);
1327 : VSIFPrintfL(fp, " <%s>%s</%s>\n",
1328 4 : pszName, pszDate, pszName);
1329 4 : CPLFree(pszDate);
1330 : }
1331 : }
1332 128 : 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 152 : else if (eFormat == GEORSS_RSS &&
1346 : (strcmp(pszElementName, "category") == 0 ||
1347 : strcmp(pszElementName, "guid") == 0 ||
1348 : strcmp(pszElementName, "source") == 0 ))
1349 : {
1350 24 : if (pszAttributeName == NULL)
1351 : {
1352 : OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
1353 12 : apszAllowedRSSFieldNames, poFeatureDefn, poFeature);
1354 : }
1355 : }
1356 : /* RSS field with attribute only */
1357 104 : 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 118 : else if (eFormat == GEORSS_ATOM &&
1368 : (strcmp(pszElementName, "category") == 0 || strcmp(pszElementName, "link") == 0))
1369 : {
1370 14 : 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 4 : apszAllowedATOMFieldNames, poFeatureDefn, poFeature);
1376 : }
1377 : }
1378 98 : 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 8 : if (strchr(pszName, '_') == NULL)
1385 : {
1386 2 : VSIFPrintfL(fp, " <%s", pszName);
1387 :
1388 2 : int bIsXHTML = FALSE;
1389 2 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "type"));
1390 2 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1391 2 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1392 : {
1393 2 : bIsXHTML = strcmp(poFeature->GetFieldAsString( iIndex ), "xhtml") == 0;
1394 : char* pszValue =
1395 2 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1396 2 : VSIFPrintfL(fp, " %s=\"%s\"", "type", pszValue);
1397 2 : CPLFree(pszValue);
1398 : }
1399 2 : CPLFree(pszFieldName);
1400 :
1401 2 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
1402 2 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1403 2 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1404 : {
1405 : char* pszValue =
1406 2 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1407 2 : VSIFPrintfL(fp, " %s=\"%s\"", "xml:lang", pszValue);
1408 2 : CPLFree(pszValue);
1409 : }
1410 2 : CPLFree(pszFieldName);
1411 :
1412 2 : pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_base"));
1413 2 : iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
1414 2 : if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
1415 : {
1416 : char* pszValue =
1417 2 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
1418 2 : VSIFPrintfL(fp, " %s=\"%s\"", "xml:base", pszValue);
1419 2 : CPLFree(pszValue);
1420 : }
1421 2 : CPLFree(pszFieldName);
1422 :
1423 2 : VSIFPrintfL(fp, ">");
1424 2 : if (bIsXHTML)
1425 2 : 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 2 : VSIFPrintfL(fp, " </%s>\n", pszName);
1434 : }
1435 : }
1436 82 : 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 82 : char* pszTagName = CPLStrdup(pszName);
1464 82 : if (IsStandardField(pszName) == FALSE)
1465 : {
1466 : int j;
1467 6 : int nCountUnderscore = 0;
1468 58 : for(j=0;pszTagName[j] != 0;j++)
1469 : {
1470 52 : if (pszTagName[j] == '_')
1471 : {
1472 4 : if (nCountUnderscore == 0)
1473 4 : pszTagName[j] = ':';
1474 4 : nCountUnderscore ++;
1475 : }
1476 48 : else if (pszTagName[j] == ' ')
1477 0 : pszTagName[j] = '_';
1478 : }
1479 6 : if (nCountUnderscore == 0)
1480 : {
1481 2 : char* pszTemp = CPLStrdup(CPLSPrintf("ogr:%s", pszTagName));
1482 2 : CPLFree(pszTagName);
1483 2 : pszTagName = pszTemp;
1484 : }
1485 : }
1486 : char* pszValue =
1487 82 : OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
1488 82 : if (poFeatureDefn->GetFieldDefn(i)->GetType() == OFTReal)
1489 : {
1490 0 : char* pszComma = strchr(pszValue, ',');
1491 0 : if (pszComma)
1492 0 : *pszComma = '.';
1493 : }
1494 82 : VSIFPrintfL(fp, " <%s>%s</%s>\n", pszTagName, pszValue, pszTagName);
1495 82 : CPLFree(pszValue);
1496 82 : CPLFree(pszTagName);
1497 : }
1498 :
1499 166 : CPLFree(pszElementName);
1500 166 : CPLFree(pszNumber);
1501 166 : CPLFree(pszAttributeName);
1502 : }
1503 :
1504 30 : CPLFree(pbUsed);
1505 :
1506 30 : OGRGeoRSSGeomDialect eGeomDialect = poDS->GetGeomDialect();
1507 30 : OGRGeometry* poGeom = poFeature->GetGeometryRef();
1508 30 : if ( poGeom != NULL && !poGeom->IsEmpty() )
1509 : {
1510 26 : char* pszURN = NULL;
1511 26 : int bSwapCoordinates = FALSE;
1512 26 : if (eGeomDialect == GEORSS_GML)
1513 : {
1514 10 : if (poSRS != NULL)
1515 : {
1516 2 : const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
1517 2 : const char* pszAuthorityCode = poSRS->GetAuthorityCode(NULL);
1518 4 : if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG") &&
1519 : pszAuthorityCode != NULL)
1520 : {
1521 2 : if (!EQUAL(pszAuthorityCode, "4326"))
1522 2 : 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 2 : const char* pszAxisName = poSRS->GetAxis(NULL, 0, NULL);
1527 2 : 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 8 : bSwapCoordinates = TRUE;
1546 : }
1547 : }
1548 :
1549 : char szCoord[75];
1550 26 : switch( wkbFlatten(poGeom->getGeometryType()) )
1551 : {
1552 : case wkbPoint:
1553 : {
1554 8 : OGRPoint* poPoint = (OGRPoint*)poGeom;
1555 8 : double x = poPoint->getX();
1556 8 : double y = poPoint->getY();
1557 8 : if (eGeomDialect == GEORSS_GML)
1558 : {
1559 4 : VSIFPrintfL(fp, " <georss:where><gml:Point");
1560 4 : if (pszURN != NULL)
1561 2 : VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
1562 4 : 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 4 : 0, 2);
1572 4 : VSIFPrintfL(fp, "><gml:pos>%s", szCoord);
1573 : }
1574 4 : VSIFPrintfL(fp, "</gml:pos></gml:Point></georss:where>\n");
1575 : }
1576 4 : else if (eGeomDialect == GEORSS_SIMPLE)
1577 : {
1578 2 : OGRMakeWktCoordinate(szCoord, y, x, 0, 2);
1579 2 : VSIFPrintfL(fp, " <georss:point>%s</georss:point>\n", szCoord);
1580 : }
1581 2 : else if (eGeomDialect == GEORSS_W3C_GEO)
1582 : {
1583 2 : OGRFormatDouble( szCoord, sizeof(szCoord), y, '.' );
1584 2 : VSIFPrintfL(fp, " <geo:lat>%s</geo:lat>\n", szCoord);
1585 2 : OGRFormatDouble( szCoord, sizeof(szCoord), x, '.' );
1586 2 : VSIFPrintfL(fp, " <geo:long>%s</geo:long>\n", szCoord);
1587 : }
1588 8 : break;
1589 : }
1590 :
1591 : case wkbLineString:
1592 : {
1593 6 : OGRLineString* poLineString = (OGRLineString*)poGeom;
1594 6 : if (eGeomDialect == GEORSS_GML)
1595 : {
1596 2 : VSIFPrintfL(fp, " <georss:where><gml:LineString");
1597 2 : if (pszURN != NULL)
1598 0 : VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
1599 2 : VSIFPrintfL(fp, "><gml:posList>\n");
1600 2 : int n = poLineString->getNumPoints();
1601 8 : for(int i=0;i<n;i++)
1602 : {
1603 6 : double x = poLineString->getX(i);
1604 6 : double y = poLineString->getY(i);
1605 : OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
1606 6 : 0, 2);
1607 6 : VSIFPrintfL(fp, "%s ", szCoord);
1608 : }
1609 2 : VSIFPrintfL(fp, "</gml:posList></gml:LineString></georss:where>\n");
1610 : }
1611 4 : else if (eGeomDialect == GEORSS_SIMPLE)
1612 : {
1613 2 : VSIFPrintfL(fp, " <georss:line>\n");
1614 2 : int n = poLineString->getNumPoints();
1615 8 : for(int i=0;i<n;i++)
1616 : {
1617 6 : double x = poLineString->getX(i);
1618 6 : double y = poLineString->getY(i);
1619 6 : OGRMakeWktCoordinate(szCoord, y, x, 0, 2);
1620 6 : VSIFPrintfL(fp, "%s ", szCoord);
1621 : }
1622 2 : VSIFPrintfL(fp, "</georss:line>\n");
1623 : }
1624 : else
1625 : {
1626 : /* Not supported */
1627 : }
1628 6 : break;
1629 : }
1630 :
1631 : case wkbPolygon:
1632 : {
1633 12 : OGRPolygon* poPolygon = (OGRPolygon*)poGeom;
1634 12 : OGRLineString* poLineString = poPolygon->getExteriorRing();
1635 12 : if (poLineString == NULL)
1636 0 : break;
1637 :
1638 12 : if (eGeomDialect == GEORSS_GML)
1639 : {
1640 4 : VSIFPrintfL(fp, " <georss:where><gml:Polygon");
1641 4 : if (pszURN != NULL)
1642 0 : VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
1643 4 : VSIFPrintfL(fp, "><gml:exterior><gml:LinearRing><gml:posList>\n");
1644 4 : int n = poLineString->getNumPoints();
1645 24 : for(int i=0;i<n;i++)
1646 : {
1647 20 : double x = poLineString->getX(i);
1648 20 : double y = poLineString->getY(i);
1649 : OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
1650 20 : 0, 2);
1651 20 : VSIFPrintfL(fp, "%s ", szCoord);
1652 : }
1653 4 : VSIFPrintfL(fp, "</gml:posList></gml:LinearRing></gml:exterior></gml:Polygon></georss:where>\n");
1654 : }
1655 8 : else if (eGeomDialect == GEORSS_SIMPLE)
1656 : {
1657 4 : VSIFPrintfL(fp, " <georss:polygon>\n");
1658 4 : int n = poLineString->getNumPoints();
1659 24 : for(int i=0;i<n;i++)
1660 : {
1661 20 : double x = poLineString->getX(i);
1662 20 : double y = poLineString->getY(i);
1663 20 : OGRMakeWktCoordinate(szCoord, y, x, 0, 2);
1664 20 : VSIFPrintfL(fp, "%s ", szCoord);
1665 : }
1666 4 : 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 26 : CPLFree(pszURN);
1680 : }
1681 :
1682 30 : if (eFormat == GEORSS_RSS)
1683 28 : VSIFPrintfL(fp, " </item>\n");
1684 : else
1685 2 : VSIFPrintfL(fp, " </entry>\n");
1686 :
1687 30 : return OGRERR_NONE;
1688 : }
1689 :
1690 :
1691 :
1692 : /************************************************************************/
1693 : /* CreateField() */
1694 : /************************************************************************/
1695 :
1696 100 : OGRErr OGRGeoRSSLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
1697 :
1698 : {
1699 100 : const char* pszName = poFieldDefn->GetNameRef();
1700 100 : 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 702 : for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
1711 : {
1712 602 : if (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
1713 : pszName ) == 0)
1714 : {
1715 0 : return OGRERR_FAILURE;
1716 : }
1717 : }
1718 :
1719 100 : if (IsStandardField(pszName))
1720 : {
1721 94 : poFeatureDefn->AddFieldDefn( poFieldDefn );
1722 94 : return OGRERR_NONE;
1723 : }
1724 :
1725 6 : 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 6 : poFeatureDefn->AddFieldDefn( poFieldDefn );
1736 6 : return OGRERR_NONE;
1737 : }
1738 : }
1739 :
1740 : #ifdef HAVE_EXPAT
1741 :
1742 552 : static void XMLCALL startElementLoadSchemaCbk(void *pUserData, const char *pszName, const char **ppszAttr)
1743 : {
1744 552 : ((OGRGeoRSSLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
1745 552 : }
1746 :
1747 552 : static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
1748 : {
1749 552 : ((OGRGeoRSSLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
1750 552 : }
1751 :
1752 1584 : static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData, const char *data, int nLen)
1753 : {
1754 1584 : ((OGRGeoRSSLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
1755 1584 : }
1756 :
1757 :
1758 : /************************************************************************/
1759 : /* LoadSchema() */
1760 : /************************************************************************/
1761 :
1762 : /** This function parses the whole file to detect the fields */
1763 36 : void OGRGeoRSSLayer::LoadSchema()
1764 : {
1765 36 : if (bHasReadSchema)
1766 0 : return;
1767 :
1768 36 : bHasReadSchema = TRUE;
1769 :
1770 36 : if (fpGeoRSS == NULL)
1771 12 : return;
1772 :
1773 24 : oSchemaParser = OGRCreateExpatXMLParser();
1774 24 : XML_SetElementHandler(oSchemaParser, ::startElementLoadSchemaCbk, ::endElementLoadSchemaCbk);
1775 24 : XML_SetCharacterDataHandler(oSchemaParser, ::dataHandlerLoadSchemaCbk);
1776 24 : XML_SetUserData(oSchemaParser, this);
1777 :
1778 24 : VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
1779 :
1780 24 : bInFeature = FALSE;
1781 24 : currentDepth = 0;
1782 24 : currentFieldDefn = NULL;
1783 24 : pszSubElementName = NULL;
1784 24 : pszSubElementValue = NULL;
1785 24 : nSubElementValueLen = 0;
1786 24 : bSameSRS = TRUE;
1787 24 : CPLFree(pszGMLSRSName);
1788 24 : pszGMLSRSName = NULL;
1789 24 : eGeomType = wkbUnknown;
1790 24 : bFoundGeom = FALSE;
1791 24 : bInTagWithSubTag = FALSE;
1792 24 : pszTagWithSubTag = NULL;
1793 24 : bStopParsing = FALSE;
1794 24 : nWithoutEventCounter = 0;
1795 24 : nTotalFeatureCount = 0;
1796 24 : setOfFoundFields = NULL;
1797 :
1798 : char aBuf[BUFSIZ];
1799 : int nDone;
1800 24 : do
1801 : {
1802 24 : nDataHandlerCounter = 0;
1803 24 : unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGeoRSS );
1804 24 : nDone = VSIFEofL(fpGeoRSS);
1805 24 : 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 24 : nWithoutEventCounter ++;
1815 : } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
1816 :
1817 24 : XML_ParserFree(oSchemaParser);
1818 :
1819 24 : 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 24 : CPLAssert(poSRS == NULL);
1827 24 : if (bSameSRS && bFoundGeom)
1828 : {
1829 18 : if (pszGMLSRSName == NULL)
1830 : {
1831 16 : poSRS = new OGRSpatialReference();
1832 16 : poSRS->SetWellKnownGeogCS( "WGS84" ); /* no AXIS definition ! */
1833 : }
1834 : else
1835 : {
1836 2 : poSRS = new OGRSpatialReference();
1837 2 : poSRS->importFromURN(pszGMLSRSName);
1838 : }
1839 : }
1840 :
1841 24 : if (eGeomType != wkbUnknown)
1842 10 : poFeatureDefn->SetGeomType(eGeomType);
1843 :
1844 24 : if (setOfFoundFields)
1845 24 : CPLHashSetDestroy(setOfFoundFields);
1846 24 : setOfFoundFields = NULL;
1847 24 : CPLFree(pszGMLSRSName);
1848 24 : pszGMLSRSName = NULL;
1849 24 : CPLFree(pszTagWithSubTag);
1850 24 : pszTagWithSubTag = NULL;
1851 :
1852 24 : VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
1853 : }
1854 :
1855 :
1856 : /************************************************************************/
1857 : /* OGRGeoRSSIsInt() */
1858 : /************************************************************************/
1859 :
1860 6 : static int OGRGeoRSSIsInt(const char* pszStr)
1861 : {
1862 : int i;
1863 :
1864 12 : while(*pszStr == ' ')
1865 0 : pszStr++;
1866 :
1867 24 : for(i=0;pszStr[i];i++)
1868 : {
1869 18 : if (pszStr[i] == '+' || pszStr[i] == '-')
1870 : {
1871 0 : if (i != 0)
1872 0 : return FALSE;
1873 : }
1874 18 : else if (!(pszStr[i] >= '0' && pszStr[i] <= '9'))
1875 0 : return FALSE;
1876 : }
1877 6 : return TRUE;
1878 : }
1879 :
1880 : /************************************************************************/
1881 : /* startElementLoadSchemaCbk() */
1882 : /************************************************************************/
1883 :
1884 552 : void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr)
1885 : {
1886 552 : if (bStopParsing) return;
1887 :
1888 552 : nWithoutEventCounter = 0;
1889 :
1890 606 : 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 54 : bInFeature = TRUE;
1894 54 : featureDepth = currentDepth;
1895 :
1896 54 : nTotalFeatureCount ++;
1897 :
1898 54 : if (setOfFoundFields)
1899 30 : CPLHashSetDestroy(setOfFoundFields);
1900 54 : setOfFoundFields = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
1901 : }
1902 518 : else if (bInTagWithSubTag && currentDepth == 3)
1903 : {
1904 20 : char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszName));
1905 20 : if (poFeatureDefn->GetFieldIndex(pszFieldName) == -1)
1906 : {
1907 20 : OGRFieldDefn newFieldDefn(pszFieldName, OFTString);
1908 20 : poFeatureDefn->AddFieldDefn(&newFieldDefn);
1909 :
1910 20 : 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 20 : }
1917 : }
1918 20 : CPLFree(pszFieldName);
1919 : }
1920 478 : else if (bInFeature && eFormat == GEORSS_ATOM &&
1921 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
1922 : {
1923 12 : CPLFree(pszTagWithSubTag);
1924 12 : pszTagWithSubTag = CPLStrdup(pszName);
1925 :
1926 12 : int count = 1;
1927 28 : while(CPLHashSetLookup(setOfFoundFields, pszTagWithSubTag) != NULL)
1928 : {
1929 4 : count ++;
1930 4 : CPLFree(pszTagWithSubTag);
1931 4 : pszTagWithSubTag = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
1932 4 : if (pszTagWithSubTag[0] == 0)
1933 : {
1934 0 : XML_StopParser(oSchemaParser, XML_FALSE);
1935 0 : bStopParsing = TRUE;
1936 0 : break;
1937 : }
1938 : }
1939 12 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
1940 :
1941 12 : bInTagWithSubTag = TRUE;
1942 : }
1943 706 : else if (bInFeature && currentDepth == featureDepth + 1 && !IS_GEO_ELEMENT(pszName))
1944 : {
1945 240 : CPLFree(pszSubElementName);
1946 240 : pszSubElementName = CPLStrdup(pszName);
1947 :
1948 240 : int count = 1;
1949 494 : while(CPLHashSetLookup(setOfFoundFields, pszSubElementName) != NULL)
1950 : {
1951 14 : count ++;
1952 14 : CPLFree(pszSubElementName);
1953 14 : pszSubElementName = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
1954 : }
1955 240 : CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszSubElementName));
1956 :
1957 : /* Create field definition for element */
1958 240 : char* pszCompatibleName = OGRGeoRSS_GetOGRCompatibleTagName(pszSubElementName);
1959 240 : int iField = poFeatureDefn->GetFieldIndex(pszCompatibleName);
1960 240 : if (iField >= 0)
1961 : {
1962 132 : currentFieldDefn = poFeatureDefn->GetFieldDefn(iField);
1963 : }
1964 108 : 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 120 : 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 20 : eFieldType = OFTDateTime;
1974 : else
1975 80 : eFieldType = OFTInteger;
1976 :
1977 100 : OGRFieldDefn newFieldDefn(pszCompatibleName, eFieldType);
1978 100 : poFeatureDefn->AddFieldDefn(&newFieldDefn);
1979 100 : currentFieldDefn = poFeatureDefn->GetFieldDefn(poFeatureDefn->GetFieldCount() - 1);
1980 :
1981 100 : 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 100 : }
1988 : }
1989 :
1990 : /* Create field definitions for attributes */
1991 302 : for(int i=0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL && !bStopParsing; i+= 2)
1992 : {
1993 : char* pszAttrCompatibleName =
1994 62 : OGRGeoRSS_GetOGRCompatibleTagName(CPLSPrintf("%s_%s", pszSubElementName, ppszAttr[i]));
1995 62 : iField = poFeatureDefn->GetFieldIndex(pszAttrCompatibleName);
1996 : OGRFieldDefn* currentAttrFieldDefn;
1997 62 : if (iField >= 0)
1998 : {
1999 0 : currentAttrFieldDefn = poFeatureDefn->GetFieldDefn(iField);
2000 : }
2001 : else
2002 : {
2003 62 : OGRFieldDefn newFieldDefn(pszAttrCompatibleName, OFTInteger);
2004 62 : poFeatureDefn->AddFieldDefn(&newFieldDefn);
2005 62 : currentAttrFieldDefn = poFeatureDefn->GetFieldDefn(poFeatureDefn->GetFieldCount() - 1);
2006 :
2007 62 : 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 62 : }
2014 : }
2015 62 : if (currentAttrFieldDefn->GetType() == OFTInteger ||
2016 : currentAttrFieldDefn->GetType() == OFTReal)
2017 : {
2018 62 : char* pszRemainingStr = NULL;
2019 62 : CPLStrtod(ppszAttr[i + 1], &pszRemainingStr);
2020 66 : if (pszRemainingStr == NULL ||
2021 : *pszRemainingStr == 0 ||
2022 : *pszRemainingStr == ' ')
2023 : {
2024 4 : if (currentAttrFieldDefn->GetType() == OFTInteger)
2025 : {
2026 4 : if (OGRGeoRSSIsInt(ppszAttr[i + 1]) == FALSE)
2027 : {
2028 0 : currentAttrFieldDefn->SetType(OFTReal);
2029 : }
2030 : }
2031 : }
2032 : else
2033 : {
2034 58 : currentAttrFieldDefn->SetType(OFTString);
2035 : }
2036 : }
2037 62 : CPLFree(pszAttrCompatibleName);
2038 : }
2039 :
2040 240 : CPLFree(pszCompatibleName);
2041 : }
2042 248 : 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 22 : if (bSameSRS)
2050 : {
2051 22 : if (pszGMLSRSName != NULL)
2052 0 : bSameSRS = FALSE;
2053 : }
2054 : }
2055 204 : 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 20 : if (bSameSRS)
2064 : {
2065 20 : int bFoundSRS = FALSE;
2066 20 : for(int i = 0; ppszAttr[i] != NULL; i+=2)
2067 : {
2068 2 : if (strcmp(ppszAttr[i], "srsName") == 0)
2069 : {
2070 2 : bFoundSRS = TRUE;
2071 2 : if (pszGMLSRSName != NULL)
2072 : {
2073 0 : if (strcmp(pszGMLSRSName , ppszAttr[i+1]) != 0)
2074 0 : bSameSRS = FALSE;
2075 : }
2076 : else
2077 2 : pszGMLSRSName = CPLStrdup(ppszAttr[i+1]);
2078 2 : break;
2079 : }
2080 : }
2081 20 : if (!bFoundSRS && pszGMLSRSName != NULL)
2082 0 : bSameSRS = FALSE;
2083 : }
2084 : }
2085 :
2086 552 : if (!bInFeature || currentDepth >= featureDepth + 1)
2087 : {
2088 498 : int nDimension = 2;
2089 634 : for(int i = 0; ppszAttr[i] != NULL; i+=2)
2090 : {
2091 136 : if (strcmp(ppszAttr[i], "srsDimension") == 0)
2092 : {
2093 0 : nDimension = atoi(ppszAttr[i+1]);
2094 0 : break;
2095 : }
2096 : }
2097 :
2098 498 : OGRwkbGeometryType eFoundGeomType = wkbUnknown;
2099 512 : if (strcmp(pszName, "georss:point") == 0 ||
2100 : IS_LAT_ELEMENT(pszName) ||
2101 : strcmp(pszName, "gml:Point") == 0)
2102 : {
2103 14 : eFoundGeomType = wkbPoint;
2104 : }
2105 484 : else if (strcmp(pszName, "gml:MultiPoint") == 0)
2106 : {
2107 0 : eFoundGeomType = wkbMultiPoint;
2108 : }
2109 494 : else if (strcmp(pszName, "georss:line") == 0 ||
2110 : strcmp(pszName, "geo:line") == 0 ||
2111 : strcmp(pszName, "gml:LineString") == 0)
2112 : {
2113 10 : eFoundGeomType = wkbLineString;
2114 : }
2115 474 : else if (strcmp(pszName, "gml:MultiLineString") == 0)
2116 : {
2117 0 : eFoundGeomType = wkbMultiLineString;
2118 : }
2119 492 : 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 18 : eFoundGeomType = wkbPolygon;
2125 : }
2126 456 : else if (strcmp(pszName, "gml:MultiPolygon") == 0)
2127 : {
2128 0 : eFoundGeomType = wkbMultiPolygon;
2129 : }
2130 :
2131 498 : if (eFoundGeomType != wkbUnknown)
2132 : {
2133 42 : if (!bFoundGeom)
2134 : {
2135 18 : eGeomType = eFoundGeomType;
2136 18 : bFoundGeom = TRUE;
2137 : }
2138 24 : else if (wkbFlatten(eGeomType) != eFoundGeomType)
2139 24 : eGeomType = wkbUnknown;
2140 :
2141 42 : if (nDimension == 3)
2142 0 : eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
2143 : }
2144 : }
2145 :
2146 552 : currentDepth++;
2147 : }
2148 :
2149 : /************************************************************************/
2150 : /* endElementLoadSchemaCbk() */
2151 : /************************************************************************/
2152 :
2153 552 : void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
2154 : {
2155 552 : if (bStopParsing) return;
2156 :
2157 552 : nWithoutEventCounter = 0;
2158 :
2159 552 : currentDepth--;
2160 :
2161 552 : if (!bInFeature)
2162 116 : return;
2163 :
2164 490 : 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 54 : bInFeature = FALSE;
2168 : }
2169 382 : else if (bInFeature && eFormat == GEORSS_ATOM &&
2170 : currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszName))
2171 : {
2172 12 : bInTagWithSubTag = FALSE;
2173 : }
2174 370 : else if (currentDepth == featureDepth + 1 && pszSubElementName)
2175 : {
2176 : /* Patch field type */
2177 240 : if (pszSubElementValue && nSubElementValueLen && currentFieldDefn)
2178 : {
2179 232 : pszSubElementValue[nSubElementValueLen] = 0;
2180 232 : if (currentFieldDefn->GetType() == OFTInteger ||
2181 : currentFieldDefn->GetType() == OFTReal)
2182 : {
2183 80 : char* pszRemainingStr = NULL;
2184 80 : CPLStrtod(pszSubElementValue, &pszRemainingStr);
2185 82 : if (pszRemainingStr == NULL ||
2186 : *pszRemainingStr == 0 ||
2187 : *pszRemainingStr == ' ')
2188 : {
2189 2 : if (currentFieldDefn->GetType() == OFTInteger)
2190 : {
2191 2 : if (OGRGeoRSSIsInt(pszSubElementValue) == FALSE)
2192 : {
2193 0 : currentFieldDefn->SetType(OFTReal);
2194 : }
2195 : }
2196 : }
2197 : else
2198 : {
2199 78 : currentFieldDefn->SetType(OFTString);
2200 : }
2201 : }
2202 : }
2203 :
2204 240 : CPLFree(pszSubElementName);
2205 240 : pszSubElementName = NULL;
2206 240 : CPLFree(pszSubElementValue);
2207 240 : pszSubElementValue = NULL;
2208 240 : nSubElementValueLen = 0;
2209 240 : currentFieldDefn = NULL;
2210 : }
2211 : }
2212 :
2213 : /************************************************************************/
2214 : /* dataHandlerLoadSchemaCbk() */
2215 : /************************************************************************/
2216 :
2217 1584 : void OGRGeoRSSLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
2218 : {
2219 1584 : if (bStopParsing) return;
2220 :
2221 1584 : nDataHandlerCounter ++;
2222 1584 : 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 1584 : nWithoutEventCounter = 0;
2231 :
2232 1584 : if (pszSubElementName)
2233 : {
2234 250 : char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue, nSubElementValueLen + nLen + 1);
2235 250 : 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 250 : pszSubElementValue = pszNewSubElementValue;
2243 250 : memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
2244 250 : nSubElementValueLen += nLen;
2245 250 : 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 : }
|