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