LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/georss - ogrgeorssdatasource.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 213
Code covered: 83.1 % Executed lines: 177

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgeorssdatasource.cpp 19641 2010-05-08 21:46:24Z rouault $
       3                 :  *
       4                 :  * Project:  GeoRSS Translator
       5                 :  * Purpose:  Implements OGRGeoRSSDataSource 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_string.h"
      33                 : #include "cpl_csv.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrgeorssdatasource.cpp 19641 2010-05-08 21:46:24Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                          OGRGeoRSSDataSource()                          */
      39                 : /************************************************************************/
      40                 : 
      41              37 : OGRGeoRSSDataSource::OGRGeoRSSDataSource()
      42                 : 
      43                 : {
      44              37 :     papoLayers = NULL;
      45              37 :     nLayers = 0;
      46                 : 
      47              37 :     fpOutput = NULL;
      48                 : 
      49              37 :     pszName = NULL;
      50                 : 
      51              37 :     eFormat = GEORSS_RSS;
      52              37 :     eGeomDialect = GEORSS_SIMPLE;
      53              37 :     bUseExtensions = FALSE;
      54              37 :     bWriteHeaderAndFooter = TRUE;
      55              37 : }
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                         ~OGRGeoRSSDataSource()                          */
      59                 : /************************************************************************/
      60                 : 
      61              37 : OGRGeoRSSDataSource::~OGRGeoRSSDataSource()
      62                 : 
      63                 : {
      64              37 :     if ( fpOutput != NULL )
      65                 :     {
      66               7 :         if (bWriteHeaderAndFooter)
      67                 :         {
      68               7 :             if (eFormat == GEORSS_RSS)
      69                 :             {
      70               6 :                 VSIFPrintfL(fpOutput, "  </channel>\n");
      71               6 :                 VSIFPrintfL(fpOutput, "</rss>\n");
      72                 :             }
      73                 :             else
      74                 :             {
      75               1 :                 VSIFPrintfL(fpOutput, "</feed>\n");
      76                 :             }
      77                 :         }
      78               7 :         VSIFCloseL( fpOutput);
      79                 :     }
      80                 : 
      81              56 :     for( int i = 0; i < nLayers; i++ )
      82              19 :         delete papoLayers[i];
      83              37 :     CPLFree( papoLayers );
      84              37 :     CPLFree( pszName );
      85              37 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                           TestCapability()                           */
      89                 : /************************************************************************/
      90                 : 
      91               0 : int OGRGeoRSSDataSource::TestCapability( const char * pszCap )
      92                 : 
      93                 : {
      94               0 :     if( EQUAL(pszCap,ODsCCreateLayer) )
      95               0 :         return TRUE;
      96               0 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
      97               0 :         return FALSE;
      98                 :     else
      99               0 :         return FALSE;
     100                 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                              GetLayer()                              */
     104                 : /************************************************************************/
     105                 : 
     106              12 : OGRLayer *OGRGeoRSSDataSource::GetLayer( int iLayer )
     107                 : 
     108                 : {
     109              12 :     if( iLayer < 0 || iLayer >= nLayers )
     110               0 :         return NULL;
     111                 :     else
     112              12 :         return papoLayers[iLayer];
     113                 : }
     114                 : 
     115                 : /************************************************************************/
     116                 : /*                            CreateLayer()                             */
     117                 : /************************************************************************/
     118                 : 
     119                 : OGRLayer * OGRGeoRSSDataSource::CreateLayer( const char * pszLayerName,
     120                 :                                              OGRSpatialReference *poSRS,
     121                 :                                              OGRwkbGeometryType eType,
     122               7 :                                              char ** papszOptions )
     123                 : 
     124                 : {
     125               7 :     if (fpOutput == NULL)
     126               0 :         return NULL;
     127                 : 
     128               7 :     if (poSRS != NULL && eGeomDialect != GEORSS_GML)
     129                 :     {
     130               1 :         OGRSpatialReference oSRS;
     131               1 :         oSRS.SetWellKnownGeogCS("WGS84");
     132               1 :         if (poSRS->IsSame(&oSRS) == FALSE)
     133                 :         {
     134                 :             CPLError(CE_Failure, CPLE_NotSupported,
     135               1 :                      "For a non GML dialect, only WGS84 SRS is supported");
     136               2 :             return NULL;
     137               0 :         }
     138                 :     }
     139                 : 
     140               6 :     nLayers++;
     141               6 :     papoLayers = (OGRGeoRSSLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGeoRSSLayer*));
     142               6 :     papoLayers[nLayers-1] = new OGRGeoRSSLayer( pszName, pszLayerName, this, poSRS, TRUE );
     143                 :     
     144               6 :     return papoLayers[nLayers-1];
     145                 : }
     146                 : 
     147                 : #ifdef HAVE_EXPAT
     148                 : /************************************************************************/
     149                 : /*                startElementValidateCbk()                             */
     150                 : /************************************************************************/
     151                 : 
     152             645 : void OGRGeoRSSDataSource::startElementValidateCbk(const char *pszName, const char **ppszAttr)
     153                 : {
     154             645 :     if (validity == GEORSS_VALIDITY_UNKNOWN)
     155                 :     {
     156              18 :         if (strcmp(pszName, "rss") == 0)
     157                 :         {
     158              11 :             validity = GEORSS_VALIDITY_VALID;
     159              11 :             eFormat = GEORSS_RSS;
     160                 :         }
     161               7 :         else if (strcmp(pszName, "feed") == 0)
     162                 :         {
     163               3 :             validity = GEORSS_VALIDITY_VALID;
     164               3 :             eFormat = GEORSS_ATOM;
     165                 :         }
     166                 :         else
     167                 :         {
     168               4 :             validity = GEORSS_VALIDITY_INVALID;
     169                 :         }
     170                 :     }
     171             645 : }
     172                 : 
     173                 : 
     174                 : /************************************************************************/
     175                 : /*                      dataHandlerValidateCbk()                        */
     176                 : /************************************************************************/
     177                 : 
     178            2029 : void OGRGeoRSSDataSource::dataHandlerValidateCbk(const char *data, int nLen)
     179                 : {
     180            2029 :     nDataHandlerCounter ++;
     181            2029 :     if (nDataHandlerCounter >= BUFSIZ)
     182                 :     {
     183               0 :         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
     184               0 :         XML_StopParser(oCurrentParser, XML_FALSE);
     185                 :     }
     186            2029 : }
     187                 : 
     188                 : 
     189             645 : static void XMLCALL startElementValidateCbk(void *pUserData, const char *pszName, const char **ppszAttr)
     190                 : {
     191             645 :     OGRGeoRSSDataSource* poDS = (OGRGeoRSSDataSource*) pUserData;
     192             645 :     poDS->startElementValidateCbk(pszName, ppszAttr);
     193             645 : }
     194                 : 
     195            2029 : static void XMLCALL dataHandlerValidateCbk(void *pUserData, const char *data, int nLen)
     196                 : {
     197            2029 :     OGRGeoRSSDataSource* poDS = (OGRGeoRSSDataSource*) pUserData;
     198            2029 :     poDS->dataHandlerValidateCbk(data, nLen);
     199            2029 : }
     200                 : #endif
     201                 : 
     202                 : /************************************************************************/
     203                 : /*                                Open()                                */
     204                 : /************************************************************************/
     205                 : 
     206              30 : int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
     207                 : 
     208                 : {
     209              30 :     if (bUpdateIn)
     210                 :     {
     211                 :         CPLError(CE_Failure, CPLE_NotSupported,
     212               0 :                     "OGR/GeoRSS driver does not support opening a file in update mode");
     213               0 :         return FALSE;
     214                 :     }
     215                 : #ifdef HAVE_EXPAT
     216              30 :     pszName = CPLStrdup( pszFilename );
     217                 : 
     218                 : /* -------------------------------------------------------------------- */
     219                 : /*      Determine what sort of object this is.                          */
     220                 : /* -------------------------------------------------------------------- */
     221                 :     VSIStatBufL sStatBuf;
     222                 : 
     223              30 :     if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
     224               3 :         return FALSE;
     225                 :     
     226              27 :     if( VSI_ISDIR(sStatBuf.st_mode) )
     227               0 :         return FALSE;
     228                 : 
     229              27 :     FILE* fp = VSIFOpenL(pszFilename, "r");
     230              27 :     if (fp == NULL)
     231               0 :         return FALSE;
     232                 :     
     233              27 :     validity = GEORSS_VALIDITY_UNKNOWN;
     234                 :     
     235              27 :     XML_Parser oParser = OGRCreateExpatXMLParser();
     236              27 :     XML_SetUserData(oParser, this);
     237              27 :     XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL);
     238              27 :     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
     239              27 :     oCurrentParser = oParser;
     240                 :     
     241                 :     char aBuf[BUFSIZ];
     242                 :     int nDone;
     243                 :     unsigned int nLen;
     244              27 :     int nCount = 0;
     245                 :     
     246                 :     /* Begin to parse the file and look for the <rss> or <feed> element */
     247                 :     /* It *MUST* be the first element of an XML file */
     248                 :     /* So once we have read the first element, we know if we can */
     249                 :     /* handle the file or not with that driver */
     250               0 :     do
     251                 :     {
     252              27 :         nDataHandlerCounter = 0;
     253              27 :         nLen = (unsigned int) VSIFReadL( aBuf, 1, sizeof(aBuf), fp );
     254              27 :         nDone = VSIFEofL(fp);
     255              27 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     256                 :         {
     257              10 :             if (nLen <= BUFSIZ-1)
     258               8 :                 aBuf[nLen] = 0;
     259                 :             else
     260               2 :                 aBuf[BUFSIZ-1] = 0;
     261              10 :             if (strstr(aBuf, "<?xml") && (strstr(aBuf, "<rss") || strstr(aBuf, "<feed")))
     262                 :             {
     263                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     264                 :                         "XML parsing of GeoRSS file failed : %s at line %d, column %d",
     265                 :                         XML_ErrorString(XML_GetErrorCode(oParser)),
     266                 :                         (int)XML_GetCurrentLineNumber(oParser),
     267               1 :                         (int)XML_GetCurrentColumnNumber(oParser));
     268                 :             }
     269              10 :             validity = GEORSS_VALIDITY_INVALID;
     270              10 :             break;
     271                 :         }
     272              17 :         if (validity == GEORSS_VALIDITY_INVALID)
     273                 :         {
     274               4 :             break;
     275                 :         }
     276              13 :         else if (validity == GEORSS_VALIDITY_VALID)
     277                 :         {
     278              13 :             break;
     279                 :         }
     280                 :         else
     281                 :         {
     282                 :             /* After reading 50 * BUFSIZ bytes, and not finding whether the file */
     283                 :             /* is GeoRSS or not, we give up and fail silently */
     284               0 :             nCount ++;
     285               0 :             if (nCount == 50)
     286               0 :                 break;
     287                 :         }
     288                 :     } while (!nDone && nLen > 0 );
     289                 :     
     290              27 :     XML_ParserFree(oParser);
     291                 :     
     292              27 :     VSIFCloseL(fp);
     293                 :     
     294              27 :     if (validity == GEORSS_VALIDITY_VALID)
     295                 :     {
     296              13 :         CPLDebug("GeoRSS", "%s seems to be a GeoRSS file.", pszFilename);
     297                 : 
     298              13 :         nLayers = 1;
     299              13 :         papoLayers = (OGRGeoRSSLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGeoRSSLayer*));
     300              13 :         papoLayers[0] = new OGRGeoRSSLayer( pszName, "georss", this, NULL, FALSE );
     301                 :     }
     302                 : 
     303              27 :     return (validity == GEORSS_VALIDITY_VALID);
     304                 : #else
     305                 :     char aBuf[256];
     306                 :     FILE* fp = VSIFOpenL(pszFilename, "r");
     307                 :     if (fp)
     308                 :     {
     309                 :         unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, 255, fp );
     310                 :         aBuf[nLen] = 0;
     311                 :         if (strstr(aBuf, "<?xml") && (strstr(aBuf, "<rss") || strstr(aBuf, "<feed")))
     312                 :         {
     313                 :             CPLError(CE_Failure, CPLE_NotSupported,
     314                 :                     "OGR/GeoRSS driver has not been built with read support. Expat library required");
     315                 :         }
     316                 :         VSIFCloseL(fp);
     317                 :     }
     318                 :     return FALSE;
     319                 : #endif
     320                 : }
     321                 : 
     322                 : 
     323                 : /************************************************************************/
     324                 : /*                               Create()                               */
     325                 : /************************************************************************/
     326                 : 
     327                 : int OGRGeoRSSDataSource::Create( const char *pszFilename, 
     328               7 :                                  char **papszOptions )
     329                 : {
     330               7 :     if( fpOutput != NULL)
     331                 :     {
     332               0 :         CPLAssert( FALSE );
     333               0 :         return FALSE;
     334                 :     }
     335                 : 
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*     Do not override exiting file.                                    */
     338                 : /* -------------------------------------------------------------------- */
     339                 :     VSIStatBufL sStatBuf;
     340                 : 
     341               7 :     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     342                 :     {
     343                 :         CPLError(CE_Failure, CPLE_NotSupported,
     344                 :                  "You have to delete %s before being able to create it with the GeoRSS driver",
     345               0 :                  pszFilename);
     346               0 :         return FALSE;
     347                 :     }
     348                 :     
     349                 : /* -------------------------------------------------------------------- */
     350                 : /*      Create the output file.                                         */
     351                 : /* -------------------------------------------------------------------- */
     352               7 :     pszName = CPLStrdup( pszFilename );
     353                 : 
     354               7 :     if( EQUAL(pszFilename,"stdout") )
     355               0 :         fpOutput = VSIFOpenL( "/vsistdout/", "w" );
     356                 :     else
     357               7 :         fpOutput = VSIFOpenL( pszFilename, "w" );
     358               7 :     if( fpOutput == NULL )
     359                 :     {
     360                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     361                 :                   "Failed to create GeoRSS file %s.", 
     362               0 :                   pszFilename );
     363               0 :         return FALSE;
     364                 :     }
     365                 : 
     366               7 :     const char* pszFormat = CSLFetchNameValue(papszOptions, "FORMAT");
     367               7 :     if (pszFormat)
     368                 :     {
     369               1 :         if (EQUAL(pszFormat, "RSS"))
     370               0 :             eFormat = GEORSS_RSS;
     371               1 :         else if (EQUAL(pszFormat, "ATOM"))
     372               1 :             eFormat = GEORSS_ATOM;
     373                 :         else
     374                 :         {
     375                 :             CPLError(CE_Warning, CPLE_NotSupported,
     376               0 :                      "Unsupported value for %s : %s", "FORMAT", pszFormat);
     377                 :         }
     378                 :     }
     379                 : 
     380               7 :     const char* pszGeomDialect = CSLFetchNameValue(papszOptions, "GEOM_DIALECT");
     381               7 :     if (pszGeomDialect)
     382                 :     {
     383               3 :         if (EQUAL(pszGeomDialect, "GML"))
     384               2 :             eGeomDialect = GEORSS_GML;
     385               1 :         else if (EQUAL(pszGeomDialect, "SIMPLE"))
     386               0 :             eGeomDialect = GEORSS_SIMPLE;
     387               1 :         else if (EQUAL(pszGeomDialect, "W3C_GEO"))
     388               1 :             eGeomDialect = GEORSS_W3C_GEO;
     389                 :         else
     390                 :         {
     391                 :             CPLError(CE_Warning, CPLE_NotSupported,
     392               0 :                      "Unsupported value for %s : %s", "GEOM_DIALECT", pszGeomDialect);
     393                 :         }
     394                 :     }
     395                 : 
     396               7 :     const char* pszWriteHeaderAndFooter = CSLFetchNameValue(papszOptions, "WRITE_HEADER_AND_FOOTER");
     397               7 :     if (pszWriteHeaderAndFooter && CSLTestBoolean(pszWriteHeaderAndFooter) == FALSE)
     398                 :     {
     399               0 :         bWriteHeaderAndFooter = FALSE;
     400               0 :         return TRUE;
     401                 :     }
     402                 : 
     403               7 :     const char* pszHeader = NULL;
     404               7 :     const char* pszTitle = NULL;
     405               7 :     const char* pszDescription = NULL;
     406               7 :     const char* pszLink = NULL;
     407               7 :     const char* pszUpdated = NULL;
     408               7 :     const char* pszAuthorName = NULL;
     409               7 :     const char* pszId = NULL;
     410                 : 
     411               7 :     pszHeader = CSLFetchNameValue(papszOptions, "HEADER");
     412                 : 
     413              13 :     if (eFormat == GEORSS_RSS && pszHeader == NULL)
     414                 :     {
     415               6 :         pszTitle = CSLFetchNameValue(papszOptions, "TITLE");
     416               6 :         if (pszTitle == NULL)
     417               6 :             pszTitle = "title";
     418                 : 
     419               6 :         pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
     420               6 :         if (pszDescription == NULL)
     421               6 :             pszDescription = "channel_description";
     422                 : 
     423               6 :         pszLink = CSLFetchNameValue(papszOptions, "LINK");
     424               6 :         if (pszLink == NULL)
     425               6 :             pszLink = "channel_link";
     426                 : 
     427                 :     }
     428               1 :     else if (eFormat == GEORSS_ATOM && pszHeader == NULL)
     429                 :     {
     430               1 :         pszTitle = CSLFetchNameValue(papszOptions, "TITLE");
     431               1 :         if (pszTitle == NULL)
     432               1 :             pszTitle = "title";
     433                 : 
     434               1 :         pszUpdated = CSLFetchNameValue(papszOptions, "UPDATED");
     435               1 :         if (pszUpdated == NULL)
     436               1 :             pszUpdated = "2009-01-01T00:00:00Z";
     437                 : 
     438               1 :         pszAuthorName = CSLFetchNameValue(papszOptions, "AUTHOR_NAME");
     439               1 :         if (pszAuthorName == NULL)
     440               1 :             pszAuthorName = "author";
     441                 : 
     442               1 :         pszId = CSLFetchNameValue(papszOptions, "ID");
     443               1 :         if (pszId == NULL)
     444               1 :             pszId = "id";
     445                 :     }
     446                 : 
     447               7 :     const char* pszUseExtensions = CSLFetchNameValue( papszOptions, "USE_EXTENSIONS");
     448               7 :     bUseExtensions =  (pszUseExtensions && CSLTestBoolean(pszUseExtensions));
     449                 : 
     450                 : /* -------------------------------------------------------------------- */
     451                 : /*     Output header of GeoRSS file.                                       */
     452                 : /* -------------------------------------------------------------------- */
     453               7 :     VSIFPrintfL(fpOutput, "<?xml version=\"1.0\"?>\n");
     454               7 :     if (eFormat == GEORSS_RSS)
     455                 :     {
     456               6 :         VSIFPrintfL(fpOutput, "<rss version=\"2.0\" ");
     457               6 :         if (eGeomDialect == GEORSS_GML)
     458               2 :             VSIFPrintfL(fpOutput, "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\"");
     459               4 :         else if (eGeomDialect == GEORSS_SIMPLE)
     460               3 :             VSIFPrintfL(fpOutput, "xmlns:georss=\"http://www.georss.org/georss\"");
     461                 :         else
     462               1 :             VSIFPrintfL(fpOutput, "xmlns:geo=\"http://www.w3.org/2003/01/geo/wgs84_pos#\"");
     463               6 :         VSIFPrintfL(fpOutput, ">\n");
     464               6 :         VSIFPrintfL(fpOutput, "  <channel>\n");
     465               6 :         if (pszHeader)
     466                 :         {
     467               0 :             VSIFPrintfL(fpOutput, "%s", pszHeader);
     468                 :         }
     469                 :         else
     470                 :         {
     471               6 :             VSIFPrintfL(fpOutput, "    <title>%s</title>\n", pszTitle);
     472               6 :             VSIFPrintfL(fpOutput, "    <description>%s</description>\n", pszDescription);
     473               6 :             VSIFPrintfL(fpOutput, "    <link>%s</link>\n", pszLink);
     474                 :         }
     475                 :     }
     476                 :     else
     477                 :     {
     478               1 :         VSIFPrintfL(fpOutput, "<feed xmlns=\"http://www.w3.org/2005/Atom\" ");
     479               1 :         if (eGeomDialect == GEORSS_GML)
     480               0 :             VSIFPrintfL(fpOutput, "xmlns:gml=\"http://www.opengis.net/gml\"");
     481               1 :         else if (eGeomDialect == GEORSS_SIMPLE)
     482               1 :             VSIFPrintfL(fpOutput, "xmlns:georss=\"http://www.georss.org/georss\"");
     483                 :         else
     484               0 :             VSIFPrintfL(fpOutput, "xmlns:geo=\"http://www.w3.org/2003/01/geo/wgs84_pos#\"");
     485               1 :         VSIFPrintfL(fpOutput, ">\n");
     486               1 :         if (pszHeader)
     487                 :         {
     488               0 :             VSIFPrintfL(fpOutput, "%s", pszHeader);
     489                 :         }
     490                 :         else
     491                 :         {
     492               1 :             VSIFPrintfL(fpOutput, "  <title>%s</title>\n", pszTitle);
     493               1 :             VSIFPrintfL(fpOutput, "  <updated>%s</updated>\n", pszUpdated);
     494               1 :             VSIFPrintfL(fpOutput, "  <author><name>%s</name></author>\n", pszAuthorName);
     495               1 :             VSIFPrintfL(fpOutput, "  <id>%s</id>\n", pszId);
     496                 :         }
     497                 :     }
     498                 : 
     499               7 :     return TRUE;
     500                 : }

Generated by: LTP GCOV extension version 1.5