1 : /**********************************************************************
2 : * $Id: gmlhandler.cpp 17910 2009-10-27 02:07:33Z chaitanya $
3 : *
4 : * Project: GML Reader
5 : * Purpose: Implementation of GMLHandler class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : **********************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
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 OR
22 : * 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 <ctype.h>
31 : #include "gmlreaderp.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 :
35 : #if HAVE_XERCES == 1
36 :
37 : /* Must be a multiple of 4 */
38 : #define MAX_TOKEN_SIZE 1000
39 :
40 : /************************************************************************/
41 : /* GMLXercesHandler() */
42 : /************************************************************************/
43 :
44 : GMLXercesHandler::GMLXercesHandler( GMLReader *poReader ) : GMLHandler(poReader)
45 : {
46 : m_nEntityCounter = 0;
47 : }
48 :
49 : /************************************************************************/
50 : /* startElement() */
51 : /************************************************************************/
52 :
53 : void GMLXercesHandler::startElement(const XMLCh* const uri,
54 : const XMLCh* const localname,
55 : const XMLCh* const qname,
56 : const Attributes& attrs )
57 :
58 : {
59 : char szElementName[MAX_TOKEN_SIZE];
60 :
61 : m_nEntityCounter = 0;
62 :
63 : /* A XMLCh character can expand to 4 bytes in UTF-8 */
64 : if (4 * tr_strlen( localname ) >= MAX_TOKEN_SIZE)
65 : {
66 : static int bWarnOnce = FALSE;
67 : XMLCh* tempBuffer = (XMLCh*) CPLMalloc(sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4 + 1));
68 : memcpy(tempBuffer, localname, sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4));
69 : tempBuffer[MAX_TOKEN_SIZE / 4] = 0;
70 : tr_strcpy( szElementName, tempBuffer );
71 : CPLFree(tempBuffer);
72 : if (!bWarnOnce)
73 : {
74 : bWarnOnce = TRUE;
75 : CPLError(CE_Warning, CPLE_AppDefined, "A too big element name has been truncated");
76 : }
77 : }
78 : else
79 : tr_strcpy( szElementName, localname );
80 :
81 : if (GMLHandler::startElement(szElementName, (void*) &attrs) == CE_Failure)
82 : {
83 : throw SAXNotSupportedException("Out of memory");
84 : }
85 : }
86 :
87 : /************************************************************************/
88 : /* endElement() */
89 : /************************************************************************/
90 : void GMLXercesHandler::endElement(const XMLCh* const uri,
91 : const XMLCh* const localname,
92 : const XMLCh* const qname )
93 :
94 : {
95 : char szElementName[MAX_TOKEN_SIZE];
96 :
97 : m_nEntityCounter = 0;
98 :
99 : /* A XMLCh character can expand to 4 bytes in UTF-8 */
100 : if (4 * tr_strlen( localname ) >= MAX_TOKEN_SIZE)
101 : {
102 : XMLCh* tempBuffer = (XMLCh*) CPLMalloc(sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4 + 1));
103 : memcpy(tempBuffer, localname, sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4));
104 : tempBuffer[MAX_TOKEN_SIZE / 4] = 0;
105 : tr_strcpy( szElementName, tempBuffer );
106 : CPLFree(tempBuffer);
107 : }
108 : else
109 : tr_strcpy( szElementName, localname );
110 :
111 : if (GMLHandler::endElement(szElementName) == CE_Failure)
112 : {
113 : throw SAXNotSupportedException("Out of memory");
114 : }
115 : }
116 :
117 : #if XERCES_VERSION_MAJOR >= 3
118 : /************************************************************************/
119 : /* characters() (xerces 3 version) */
120 : /************************************************************************/
121 :
122 : void GMLXercesHandler::characters(const XMLCh* const chars_in,
123 : const XMLSize_t length )
124 : {
125 : char* utf8String = tr_strdup(chars_in);
126 : int nLen = strlen(utf8String);
127 : OGRErr eErr = GMLHandler::dataHandler(utf8String, nLen);
128 : CPLFree(utf8String);
129 : if (eErr == CE_Failure)
130 : {
131 : throw SAXNotSupportedException("Out of memory");
132 : }
133 : }
134 :
135 : #else
136 : /************************************************************************/
137 : /* characters() (xerces 2 version) */
138 : /************************************************************************/
139 :
140 : void GMLXercesHandler::characters(const XMLCh* const chars_in,
141 : const unsigned int length )
142 :
143 : {
144 : char* utf8String = tr_strdup(chars_in);
145 : int nLen = strlen(utf8String);
146 : OGRErr eErr = GMLHandler::dataHandler(utf8String, nLen);
147 : CPLFree(utf8String);
148 : if (eErr == CE_Failure)
149 : {
150 : throw SAXNotSupportedException("Out of memory");
151 : }
152 : }
153 : #endif
154 :
155 : /************************************************************************/
156 : /* fatalError() */
157 : /************************************************************************/
158 :
159 : void GMLXercesHandler::fatalError( const SAXParseException &exception)
160 :
161 : {
162 : char *pszErrorMessage;
163 :
164 : pszErrorMessage = tr_strdup( exception.getMessage() );
165 : CPLError( CE_Failure, CPLE_AppDefined,
166 : "XML Parsing Error: %s\n",
167 : pszErrorMessage );
168 :
169 : CPLFree( pszErrorMessage );
170 : }
171 :
172 : /************************************************************************/
173 : /* startEntity() */
174 : /************************************************************************/
175 :
176 : void GMLXercesHandler::startEntity (const XMLCh *const name)
177 : {
178 : m_nEntityCounter ++;
179 : if (m_nEntityCounter > 1000 && !m_poReader->HasStoppedParsing())
180 : {
181 : throw SAXNotSupportedException("File probably corrupted (million laugh pattern)");
182 : }
183 : }
184 :
185 : /************************************************************************/
186 : /* GetFID() */
187 : /************************************************************************/
188 :
189 : char* GMLXercesHandler::GetFID(void* attr)
190 : {
191 : const Attributes* attrs = (const Attributes*) attr;
192 : int nFIDIndex;
193 : XMLCh anFID[100];
194 :
195 : tr_strcpy( anFID, "fid" );
196 : nFIDIndex = attrs->getIndex( anFID );
197 : if( nFIDIndex != -1 )
198 : return tr_strdup( attrs->getValue( nFIDIndex ) );
199 :
200 : return NULL;
201 : }
202 :
203 : /************************************************************************/
204 : /* GetAttributes() */
205 : /************************************************************************/
206 :
207 : char* GMLXercesHandler::GetAttributes(void* attr)
208 : {
209 : const Attributes* attrs = (const Attributes*) attr;
210 : CPLString osRes;
211 : char *pszString;
212 :
213 : for(unsigned int i=0; i < attrs->getLength(); i++)
214 : {
215 : osRes += " ";
216 : pszString = tr_strdup(attrs->getQName(i));
217 : osRes += pszString;
218 : CPLFree( pszString );
219 : osRes += "=\"";
220 : pszString = tr_strdup(attrs->getValue(i));
221 : osRes += pszString;
222 : CPLFree( pszString );
223 : osRes += "\"";
224 : }
225 : return CPLStrdup(osRes);
226 : }
227 :
228 : #else
229 :
230 :
231 : /************************************************************************/
232 : /* GMLExpatHandler() */
233 : /************************************************************************/
234 :
235 23 : GMLExpatHandler::GMLExpatHandler( GMLReader *poReader, XML_Parser oParser ) : GMLHandler(poReader)
236 :
237 : {
238 23 : m_oParser = oParser;
239 23 : m_bStopParsing = FALSE;
240 23 : m_nDataHandlerCounter = 0;
241 23 : }
242 :
243 : /************************************************************************/
244 : /* startElement() */
245 : /************************************************************************/
246 :
247 702 : OGRErr GMLExpatHandler::startElement(const char *pszName, void* attr )
248 :
249 : {
250 702 : if (m_bStopParsing)
251 0 : return CE_Failure;
252 :
253 702 : const char* pszColon = strchr(pszName, ':');
254 702 : if (pszColon)
255 637 : pszName = pszColon + 1;
256 :
257 702 : if (GMLHandler::startElement(pszName, attr) == CE_Failure)
258 : {
259 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
260 0 : m_bStopParsing = TRUE;
261 0 : XML_StopParser(m_oParser, XML_FALSE);
262 0 : return CE_Failure;
263 : }
264 :
265 702 : return CE_None;
266 : }
267 :
268 : /************************************************************************/
269 : /* endElement() */
270 : /************************************************************************/
271 702 : OGRErr GMLExpatHandler::endElement(const char* pszName )
272 :
273 : {
274 702 : if (m_bStopParsing)
275 0 : return CE_Failure;
276 :
277 702 : const char* pszColon = strchr(pszName, ':');
278 702 : if (pszColon)
279 637 : pszName = pszColon + 1;
280 :
281 702 : if (GMLHandler::endElement(pszName) == CE_Failure)
282 : {
283 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
284 0 : m_bStopParsing = TRUE;
285 0 : XML_StopParser(m_oParser, XML_FALSE);
286 0 : return CE_Failure;
287 : }
288 :
289 702 : return CE_None;
290 : }
291 :
292 : /************************************************************************/
293 : /* characters() */
294 : /************************************************************************/
295 :
296 1801 : OGRErr GMLExpatHandler::dataHandler(const char *data, int nLen)
297 :
298 : {
299 1801 : if (m_bStopParsing)
300 0 : return CE_Failure;
301 :
302 1801 : m_nDataHandlerCounter ++;
303 1801 : if (m_nDataHandlerCounter >= BUFSIZ)
304 : {
305 0 : CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
306 0 : m_bStopParsing = TRUE;
307 0 : XML_StopParser(m_oParser, XML_FALSE);
308 0 : return CE_Failure;
309 : }
310 :
311 1801 : if (GMLHandler::dataHandler(data, nLen) == CE_Failure)
312 : {
313 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
314 0 : m_bStopParsing = TRUE;
315 0 : XML_StopParser(m_oParser, XML_FALSE);
316 0 : return CE_Failure;
317 : }
318 :
319 1801 : return CE_None;
320 : }
321 :
322 : /************************************************************************/
323 : /* GetFID() */
324 : /************************************************************************/
325 :
326 56 : char* GMLExpatHandler::GetFID(void* attr)
327 : {
328 56 : const char** papszIter = (const char** )attr;
329 112 : while(*papszIter)
330 : {
331 52 : if (strcmp(*papszIter, "fid") == 0)
332 : {
333 52 : return CPLStrdup(papszIter[1]);
334 : }
335 :
336 0 : papszIter += 2;
337 : }
338 4 : return NULL;
339 : }
340 :
341 : /************************************************************************/
342 : /* GetAttributes() */
343 : /************************************************************************/
344 :
345 136 : char* GMLExpatHandler::GetAttributes(void* attr)
346 : {
347 136 : const char** papszIter = (const char** )attr;
348 136 : CPLString osRes;
349 285 : while(*papszIter)
350 : {
351 13 : osRes += " ";
352 13 : osRes += *papszIter;
353 13 : osRes += "=\"";
354 13 : osRes += papszIter[1];
355 13 : osRes += "\"";
356 :
357 13 : papszIter += 2;
358 : }
359 136 : return CPLStrdup( osRes );
360 : }
361 :
362 : #endif
363 :
364 :
365 :
366 : /************************************************************************/
367 : /* GMLHandler() */
368 : /************************************************************************/
369 :
370 23 : GMLHandler::GMLHandler( GMLReader *poReader )
371 :
372 : {
373 23 : m_poReader = poReader;
374 23 : m_pszCurField = NULL;
375 23 : m_pszGeometry = NULL;
376 23 : m_nGeomAlloc = m_nGeomLen = 0;
377 23 : m_nDepthFeature = m_nDepth = 0;
378 23 : }
379 :
380 : /************************************************************************/
381 : /* ~GMLHandler() */
382 : /************************************************************************/
383 :
384 23 : GMLHandler::~GMLHandler()
385 :
386 : {
387 23 : CPLFree( m_pszCurField );
388 23 : CPLFree( m_pszGeometry );
389 23 : }
390 :
391 :
392 : /************************************************************************/
393 : /* startElement() */
394 : /************************************************************************/
395 :
396 702 : OGRErr GMLHandler::startElement(const char *pszName, void* attr )
397 :
398 : {
399 702 : GMLReadState *poState = m_poReader->GetState();
400 :
401 702 : int nLNLenBytes = strlen(pszName);
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* If we are in the midst of collecting a feature attribute */
405 : /* value, then this must be a complex attribute which we don't */
406 : /* try to collect for now, so just terminate the field */
407 : /* collection. */
408 : /* -------------------------------------------------------------------- */
409 702 : if( m_pszCurField != NULL )
410 : {
411 44 : CPLFree( m_pszCurField );
412 44 : m_pszCurField = NULL;
413 : }
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* If we are collecting geometry, or if we determine this is a */
417 : /* geometry element then append to the geometry info. */
418 : /* -------------------------------------------------------------------- */
419 702 : if( m_pszGeometry != NULL
420 : || IsGeometryElement( pszName ) )
421 : {
422 : /* should save attributes too! */
423 :
424 136 : if( m_pszGeometry == NULL )
425 62 : m_nGeometryDepth = poState->m_nPathLength;
426 :
427 136 : char* pszAttributes = GetAttributes(attr);
428 :
429 136 : if( m_nGeomLen + nLNLenBytes + 4 + strlen( pszAttributes ) >
430 : m_nGeomAlloc )
431 : {
432 : m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLenBytes + 1000 +
433 62 : strlen( pszAttributes ));
434 : char* pszNewGeometry = (char *)
435 62 : VSIRealloc( m_pszGeometry, m_nGeomAlloc);
436 62 : if (pszNewGeometry == NULL)
437 : {
438 0 : CPLFree(pszAttributes);
439 0 : return CE_Failure;
440 : }
441 62 : m_pszGeometry = pszNewGeometry;
442 : }
443 :
444 136 : strcpy( m_pszGeometry+m_nGeomLen++, "<" );
445 136 : strcpy( m_pszGeometry+m_nGeomLen, pszName );
446 136 : m_nGeomLen += nLNLenBytes;
447 : /* saving attributes */
448 136 : strcat( m_pszGeometry + m_nGeomLen, pszAttributes );
449 136 : m_nGeomLen += strlen( pszAttributes );
450 136 : CPLFree(pszAttributes);
451 136 : strcat( m_pszGeometry + (m_nGeomLen++), ">" );
452 : }
453 :
454 : /* -------------------------------------------------------------------- */
455 : /* Is it a feature? If so push a whole new state, and return. */
456 : /* -------------------------------------------------------------------- */
457 566 : else if( m_poReader->IsFeatureElement( pszName ) )
458 : {
459 56 : char* pszFID = GetFID(attr);
460 :
461 56 : m_poReader->PushFeature( pszName, pszFID);
462 :
463 56 : CPLFree(pszFID);
464 :
465 56 : m_nDepthFeature = m_nDepth;
466 56 : m_nDepth ++;
467 :
468 56 : return CE_None;
469 : }
470 :
471 : /* -------------------------------------------------------------------- */
472 : /* If it is (or at least potentially is) a simple attribute, */
473 : /* then start collecting it. */
474 : /* -------------------------------------------------------------------- */
475 510 : else if( m_poReader->IsAttributeElement( pszName ) )
476 : {
477 223 : CPLFree( m_pszCurField );
478 223 : m_pszCurField = CPLStrdup("");
479 : }
480 :
481 : /* -------------------------------------------------------------------- */
482 : /* Push the element onto the current state's path. */
483 : /* -------------------------------------------------------------------- */
484 646 : poState->PushPath( pszName );
485 :
486 646 : m_nDepth ++;
487 :
488 646 : return CE_None;
489 : }
490 :
491 : /************************************************************************/
492 : /* endElement() */
493 : /************************************************************************/
494 702 : OGRErr GMLHandler::endElement(const char* pszName )
495 :
496 : {
497 702 : m_nDepth --;
498 :
499 702 : GMLReadState *poState = m_poReader->GetState();
500 :
501 702 : int nLNLenBytes = strlen(pszName);
502 :
503 : /* -------------------------------------------------------------------- */
504 : /* Is this closing off an attribute value? We assume so if */
505 : /* we are collecting an attribute value and got to this point. */
506 : /* We don't bother validating that the closing tag matches the */
507 : /* opening tag. */
508 : /* -------------------------------------------------------------------- */
509 702 : if( m_pszCurField != NULL )
510 : {
511 : CPLAssert( poState->m_poFeature != NULL );
512 :
513 179 : m_poReader->SetFeatureProperty( pszName, m_pszCurField );
514 179 : CPLFree( m_pszCurField );
515 179 : m_pszCurField = NULL;
516 : }
517 :
518 : /* -------------------------------------------------------------------- */
519 : /* If we are collecting Geometry than store it, and consider if */
520 : /* this is the end of the geometry. */
521 : /* -------------------------------------------------------------------- */
522 702 : if( m_pszGeometry != NULL )
523 : {
524 : /* should save attributes too! */
525 :
526 136 : if( m_nGeomLen + nLNLenBytes + 4 > m_nGeomAlloc )
527 : {
528 0 : m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLenBytes + 1000);
529 : char* pszNewGeometry = (char *)
530 0 : VSIRealloc( m_pszGeometry, m_nGeomAlloc);
531 0 : if (pszNewGeometry == NULL)
532 : {
533 0 : return CE_Failure;
534 : }
535 0 : m_pszGeometry = pszNewGeometry;
536 : }
537 :
538 136 : strcat( m_pszGeometry+m_nGeomLen, "</" );
539 136 : strcpy( m_pszGeometry+m_nGeomLen+2, pszName );
540 136 : strcat( m_pszGeometry+m_nGeomLen+nLNLenBytes+2, ">" );
541 136 : m_nGeomLen += nLNLenBytes + 3;
542 :
543 136 : if( poState->m_nPathLength == m_nGeometryDepth+1 )
544 : {
545 62 : if( poState->m_poFeature != NULL )
546 54 : poState->m_poFeature->SetGeometryDirectly( m_pszGeometry );
547 : else
548 8 : CPLFree( m_pszGeometry );
549 :
550 62 : m_pszGeometry = NULL;
551 62 : m_nGeomAlloc = m_nGeomLen = 0;
552 : }
553 : }
554 :
555 : /* -------------------------------------------------------------------- */
556 : /* If we are collecting a feature, and this element tag matches */
557 : /* element name for the class, then we have finished the */
558 : /* feature, and we pop the feature read state. */
559 : /* -------------------------------------------------------------------- */
560 702 : if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
561 : && strcmp(pszName,
562 : poState->m_poFeature->GetClass()->GetElementName()) == 0 )
563 : {
564 56 : m_poReader->PopState();
565 : }
566 :
567 : /* -------------------------------------------------------------------- */
568 : /* Otherwise, we just pop the element off the local read states */
569 : /* element stack. */
570 : /* -------------------------------------------------------------------- */
571 : else
572 : {
573 646 : if( strcmp(pszName,poState->GetLastComponent()) == 0 )
574 646 : poState->PopPath();
575 : else
576 : {
577 : CPLAssert( FALSE );
578 : }
579 : }
580 :
581 702 : return CE_None;
582 : }
583 :
584 : /************************************************************************/
585 : /* characters() */
586 : /************************************************************************/
587 :
588 1801 : OGRErr GMLHandler::dataHandler(const char *data, int nLen)
589 :
590 : {
591 1801 : int nIter = 0;
592 :
593 1801 : if( m_pszCurField != NULL )
594 : {
595 191 : int nCurFieldLength = strlen(m_pszCurField);
596 :
597 : // Ignore white space
598 191 : if (nCurFieldLength == 0)
599 : {
600 1198 : while (nIter < nLen &&
601 784 : ( data[nIter] == ' ' || data[nIter] == 10 || data[nIter]== 13 || data[nIter] == '\t') )
602 32 : nIter ++;
603 : }
604 :
605 191 : int nCharsLen = nLen - nIter;
606 :
607 : char *pszNewCurField = (char *)
608 : VSIRealloc( m_pszCurField,
609 191 : nCurFieldLength+ nCharsLen +1 );
610 191 : if (pszNewCurField == NULL)
611 : {
612 0 : return CE_Failure;
613 : }
614 191 : m_pszCurField = pszNewCurField;
615 191 : memcpy( m_pszCurField + nCurFieldLength, data + nIter, nCharsLen);
616 191 : nCurFieldLength += nCharsLen;
617 :
618 191 : m_pszCurField[nCurFieldLength] = '\0';
619 : }
620 1610 : else if( m_pszGeometry != NULL )
621 : {
622 : // Ignore white space
623 149 : if (m_nGeomLen == 0)
624 : {
625 0 : while (nIter < nLen &&
626 0 : ( data[nIter] == ' ' || data[nIter] == 10 || data[nIter]== 13 || data[nIter] == '\t') )
627 0 : nIter ++;
628 : }
629 :
630 149 : int nCharsLen = nLen - nIter;
631 :
632 149 : if( m_nGeomLen + nCharsLen + 4 > m_nGeomAlloc )
633 : {
634 0 : m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nCharsLen + 1000);
635 : char* pszNewGeometry = (char *)
636 0 : VSIRealloc( m_pszGeometry, m_nGeomAlloc);
637 0 : if (pszNewGeometry == NULL)
638 : {
639 0 : return CE_Failure;
640 : }
641 0 : m_pszGeometry = pszNewGeometry;
642 : }
643 :
644 149 : memcpy( m_pszGeometry+m_nGeomLen, data + nIter, nCharsLen);
645 149 : m_nGeomLen += nCharsLen;
646 149 : m_pszGeometry[m_nGeomLen] = '\0';
647 : }
648 :
649 1801 : return CE_None;
650 : }
651 :
652 :
653 : /************************************************************************/
654 : /* IsGeometryElement() */
655 : /************************************************************************/
656 :
657 628 : int GMLHandler::IsGeometryElement( const char *pszElement )
658 :
659 : {
660 : return strcmp(pszElement,"Polygon") == 0
661 : || strcmp(pszElement,"MultiPolygon") == 0
662 : || strcmp(pszElement,"MultiPoint") == 0
663 : || strcmp(pszElement,"MultiLineString") == 0
664 : || strcmp(pszElement,"MultiSurface") == 0
665 : || strcmp(pszElement,"GeometryCollection") == 0
666 : || strcmp(pszElement,"Point") == 0
667 : || strcmp(pszElement,"Curve") == 0
668 : || strcmp(pszElement,"Surface") == 0
669 : || strcmp(pszElement,"PolygonPatch") == 0
670 628 : || strcmp(pszElement,"LineString") == 0;
671 : }
|