LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - resolvexlinks.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 218 182 83.5 %
Date: 2012-12-26 Functions: 8 8 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: resolvexlinks.cpp 22205 2011-04-18 21:17:30Z rouault $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Implementation of GMLReader::ResolveXlinks() method.
       6                 :  * Author:   Chaitanya kumar CH, chaitanya@osgeo.in
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Chaitanya kumar CH
      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 "gmlreader.h"
      31                 : #include "cpl_error.h"
      32                 : 
      33                 : CPL_CVSID("$Id: resolvexlinks.cpp 22205 2011-04-18 21:17:30Z rouault $");
      34                 : 
      35                 : #include "gmlreaderp.h"
      36                 : #include "cpl_conv.h"
      37                 : #include "cpl_string.h"
      38                 : #include "cpl_http.h"
      39                 : 
      40                 : #include <stack>
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                              GetID()                                 */
      44                 : /*                                                                      */
      45                 : /*      Returns the reference to the gml:id of psNode. NULL if not      */
      46                 : /*      found.                                                          */
      47                 : /************************************************************************/
      48                 : 
      49          863246 : static const char* GetID( CPLXMLNode * psNode )
      50                 : 
      51                 : {
      52          863246 :     if( psNode == NULL )
      53               0 :         return NULL;
      54                 : 
      55                 :     CPLXMLNode *psChild;
      56         2236863 :     for( psChild = psNode->psChild; psChild != NULL; psChild = psChild->psNext )
      57                 :     {
      58         1470253 :         if( psChild->eType == CXT_Attribute
      59                 :             && EQUAL(psChild->pszValue, "gml:id") )
      60                 :         {
      61           96636 :             return psChild->psChild->pszValue;
      62                 :         }
      63                 :     }
      64          766610 :     return NULL;
      65                 : }
      66                 : 
      67                 : /************************************************************************/
      68                 : /*                       CompareNodeIDs()                               */
      69                 : /*                                                                      */
      70                 : /*      Compares two nodes by their IDs                                 */
      71                 : /************************************************************************/
      72                 : 
      73                 : /*static int CompareNodeIDs( CPLXMLNode * psNode1, CPLXMLNode * psNode2 )
      74                 : 
      75                 : {
      76                 :     if( psNode2 == NULL )
      77                 :         return TRUE;
      78                 : 
      79                 :     if( psNode1 == NULL )
      80                 :         return FALSE;
      81                 : 
      82                 :     return ( strcmp( GetID(psNode2), GetID(psNode1) ) > 0 );
      83                 : }*/
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                       BuildIDIndex()                                 */
      87                 : /*                                                                      */
      88                 : /*      Returns an array of nodes sorted by their gml:id strings        */
      89                 : /*      XXX: This method can be used to build an array of pointers to   */
      90                 : /*      nodes sorted by their id values.                                */
      91                 : /************************************************************************/
      92                 : /*
      93                 : static std::vector<CPLXMLNode*> BuildIDIndex( CPLXMLNode* psNode,
      94                 :                                    std::vector<CPLXMLNode*> &apsNode )
      95                 : 
      96                 : {
      97                 :     CPLXMLNode *psSibling;
      98                 :     for( psSibling = psNode; psSibling != NULL; psSibling = psSibling->psNext )
      99                 :     {
     100                 :         if( GetID( psSibling ) != NULL )
     101                 :             apsNode.push_back( psSibling );
     102                 :         BuildIDIndex( psNode->psChild, apsNode );
     103                 :     }
     104                 :     return NULL;
     105                 : }*/
     106                 : 
     107                 : /************************************************************************/
     108                 : /*                          FindElementByID()                           */
     109                 : /*                                                                      */
     110                 : /*      Find a node with the indicated "gml:id" in the node tree and    */
     111                 : /*      it's siblings.                                                  */
     112                 : /************************************************************************/
     113                 : 
     114          820274 : static CPLXMLNode *FindElementByID( CPLXMLNode * psRoot,
     115                 :                                     const char *pszID )
     116                 : 
     117                 : {
     118          820274 :     if( psRoot == NULL )
     119           26638 :         return NULL;
     120                 : 
     121          793636 :     CPLXMLNode *psSibling, *psReturn = NULL;
     122                 : 
     123                 : // check for id attribute
     124         2231140 :     for( psSibling = psRoot; psSibling != NULL; psSibling = psSibling->psNext)
     125                 :     {
     126         1438291 :         if( psSibling->eType == CXT_Element )
     127                 :         {
     128                 :             // check that sibling for id value
     129          863246 :             const char* pszIDOfSibling = GetID( psSibling );
     130          863246 :             if( pszIDOfSibling != NULL && EQUAL( pszIDOfSibling, pszID) )
     131             787 :                 return psSibling;
     132                 :         }
     133                 :     }
     134                 : 
     135                 : // search the child elements of all the psRoot's siblings
     136         2181833 :     for( psSibling = psRoot; psSibling != NULL; psSibling = psSibling->psNext)
     137                 :     {
     138         1394291 :         if( psSibling->eType == CXT_Element )
     139                 :         {
     140          819411 :             psReturn = FindElementByID( psSibling->psChild, pszID );
     141          819411 :             if( psReturn != NULL )
     142            5307 :                 return psReturn;
     143                 :         }
     144                 :     }
     145          787542 :     return NULL;
     146                 : }
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                          RemoveIDs()                                 */
     150                 : /*                                                                      */
     151                 : /*      Remove all the gml:id nodes. Doesn't check psRoot's siblings    */
     152                 : /************************************************************************/
     153                 : 
     154            3902 : static void RemoveIDs( CPLXMLNode * psRoot )
     155                 : 
     156                 : {
     157            3902 :     if( psRoot == NULL )
     158               0 :         return;
     159                 : 
     160            3902 :     CPLXMLNode *psChild = psRoot->psChild;
     161                 : 
     162                 : // check for id attribute
     163           11646 :     while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL(psChild->pszValue, "gml:id")))
     164            3842 :         psChild = psChild->psNext;
     165            3902 :     CPLRemoveXMLChild( psRoot, psChild );
     166            3902 :     CPLDestroyXMLNode( psChild );
     167                 : 
     168                 : // search the child elements of psRoot
     169            9133 :     for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext)
     170            5231 :         if( psChild->eType == CXT_Element )
     171            3115 :             RemoveIDs( psChild );
     172                 : }
     173                 : 
     174                 : /************************************************************************/
     175                 : /*                          TrimTree()                                  */
     176                 : /*                                                                      */
     177                 : /*      Remove all nodes without a gml:id node in the descendents.      */
     178                 : /*      Returns TRUE if there is a gml:id node in the descendents.      */
     179                 : /************************************************************************/
     180                 : 
     181            9170 : static int TrimTree( CPLXMLNode * psRoot )
     182                 : 
     183                 : {
     184            9170 :     if( psRoot == NULL )
     185               0 :         return FALSE;
     186                 : 
     187            9170 :     CPLXMLNode *psChild = psRoot->psChild;
     188                 : 
     189                 : // check for id attribute
     190           32930 :     while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL(psChild->pszValue, "gml:id")))
     191           14590 :         psChild = psChild->psNext;
     192                 : 
     193            9170 :     if( psChild != NULL )
     194             845 :         return TRUE;
     195                 : 
     196                 : // search the child elements of psRoot
     197            8325 :     int bReturn = FALSE, bRemove;
     198           31240 :     for( psChild = psRoot->psChild; psChild != NULL;)
     199                 :     {
     200           14590 :         CPLXMLNode* psNextChild = psChild->psNext;
     201           14590 :         if( psChild->eType == CXT_Element )
     202                 :         {
     203            9160 :             bRemove = TrimTree( psChild );
     204            9160 :             if( bRemove )
     205                 :             {
     206            3855 :                 bReturn = bRemove;
     207                 :             }
     208                 :             else
     209                 :             {
     210                 :                 //remove this child
     211            5305 :                 CPLRemoveXMLChild( psRoot, psChild );
     212            5305 :                 CPLDestroyXMLNode( psChild );
     213                 :             }
     214                 :         }
     215                 : 
     216           14590 :         psChild = psNextChild;
     217                 :     }
     218            8325 :     return bReturn;
     219                 : }
     220                 : 
     221                 : /************************************************************************/
     222                 : /*                          CorrectURLs()                               */
     223                 : /*                                                                      */
     224                 : /*  Processes the node and all it's children recursively. Siblings of   */
     225                 : /*  psRoot are ignored.                                                 */
     226                 : /*  - Replaces all every URL in URL#id pairs with pszURL.               */
     227                 : /*  - Leaves it alone if the paths are same or the URL is not relative. */
     228                 : /*  - If it is relative, the path from pszURL is prepended.             */
     229                 : /************************************************************************/
     230                 : 
     231           11334 : static void CorrectURLs( CPLXMLNode * psRoot, const char *pszURL )
     232                 : 
     233                 : {
     234           11334 :     if( psRoot == NULL || pszURL == NULL )
     235               0 :         return;
     236           11334 :     if( pszURL[0] == '\0' )
     237               0 :         return;
     238                 : 
     239           11334 :     CPLXMLNode *psChild = psRoot->psChild;
     240                 : 
     241                 : // check for xlink:href attribute
     242           39778 :     while( psChild != NULL && !( ( psChild->eType == CXT_Attribute ) &&
     243                 :                                  ( EQUAL(psChild->pszValue, "xlink:href") )) )
     244           17110 :         psChild = psChild->psNext;
     245                 : 
     246           11424 :     if( psChild != NULL &&
     247                 :         !( strstr( psChild->psChild->pszValue, pszURL ) == psChild->psChild->pszValue
     248              90 :         && psChild->psChild->pszValue[strlen(pszURL)] == '#' ) )
     249                 :     {
     250                 :     //href has a different url
     251                 :         size_t nLen;
     252                 :         char *pszNew;
     253            1097 :         if( psChild->psChild->pszValue[0] == '#' )
     254                 :         {
     255                 :         //empty URL: prepend the given URL
     256                 :             nLen = CPLStrnlen( pszURL, 1024 ) +
     257             871 :                    CPLStrnlen( psChild->psChild->pszValue, 1024 ) + 1;
     258             871 :             pszNew = (char *)CPLMalloc( nLen * sizeof(char));
     259             871 :             CPLStrlcpy( pszNew, pszURL, nLen );
     260             871 :             CPLStrlcat( pszNew, psChild->psChild->pszValue, nLen );
     261             871 :             CPLSetXMLValue( psRoot, "#xlink:href", pszNew );
     262             871 :             CPLFree( pszNew );
     263                 :         }
     264                 :         else
     265                 :         {
     266                 :             size_t nPathLen;
     267            4972 :             for( nPathLen = strlen(pszURL);
     268            2486 :                  nPathLen > 0 && pszURL[nPathLen - 1] != '/'
     269            2260 :                               && pszURL[nPathLen - 1] != '\\';
     270                 :                  nPathLen--);
     271                 : 
     272             226 :             if( strncmp( pszURL, psChild->psChild->pszValue, nPathLen ) != 0 )
     273                 :             {
     274                 :             //different path
     275                 :                 int nURLLen = strchr( psChild->psChild->pszValue, '#' ) -
     276             218 :                               psChild->psChild->pszValue;
     277             218 :                 char *pszURLWithoutID = (char *)CPLMalloc( (nURLLen+1) * sizeof(char));
     278             218 :                 strncpy( pszURLWithoutID, psChild->psChild->pszValue, nURLLen );
     279             218 :                 pszURLWithoutID[nURLLen] = '\0';
     280                 : 
     281             218 :                 if( CPLIsFilenameRelative( pszURLWithoutID ) &&
     282                 :                     strstr( pszURLWithoutID, ":" ) == NULL )
     283                 :                 {
     284                 :                     //relative URL: prepend the path of pszURL
     285                 :                     nLen = nPathLen +
     286             134 :                            CPLStrnlen( psChild->psChild->pszValue, 1024 ) + 1;
     287             134 :                     pszNew = (char *)CPLMalloc( nLen * sizeof(char));
     288                 :                     size_t i;
     289            2914 :                     for( i = 0; i < nPathLen; i++ )
     290            2780 :                         pszNew[i] = pszURL[i];
     291             134 :                     pszNew[nPathLen] = '\0';
     292             134 :                     CPLStrlcat( pszNew, psChild->psChild->pszValue, nLen );
     293             134 :                     CPLSetXMLValue( psRoot, "#xlink:href", pszNew );
     294             134 :                     CPLFree( pszNew );
     295                 :                 }
     296             218 :                 CPLFree( pszURLWithoutID );
     297                 :             }
     298                 :         }
     299                 :     }
     300                 : 
     301                 : // search the child elements of psRoot
     302           30140 :     for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext)
     303           18806 :         if( psChild->eType == CXT_Element )
     304           10537 :             CorrectURLs( psChild, pszURL );
     305                 : }
     306                 : 
     307                 : /************************************************************************/
     308                 : /*                          FindTreeByURL()                             */
     309                 : /*                                                                      */
     310                 : /*  Find a doc tree that is located at pszURL.                          */
     311                 : /*  If not present in ppapsRoot, it updates it and ppapszResourceHREF.  */
     312                 : /************************************************************************/
     313                 : 
     314             863 : static CPLXMLNode *FindTreeByURL( CPLXMLNode *** ppapsRoot,
     315                 :                                   char *** ppapszResourceHREF,
     316                 :                                   const char *pszURL )
     317                 : 
     318                 : {
     319             863 :     if( *ppapsRoot == NULL || ppapszResourceHREF == NULL )
     320               0 :         return NULL;
     321                 : 
     322                 : //if found in ppapszResourceHREF
     323                 :     int i, nItems;
     324                 :     char *pszLocation;
     325             863 :     if( ( i = CSLFindString( *ppapszResourceHREF, pszURL )) >= 0 )
     326                 :     {
     327                 :     //return corresponding psRoot
     328             858 :         return (*ppapsRoot)[i];
     329                 :     }
     330                 :     else
     331                 :     {
     332               5 :         CPLXMLNode *psSrcTree = NULL, *psSibling;
     333               5 :         pszLocation = CPLStrdup( pszURL );
     334                 :         //if it is part of filesystem
     335               5 :         if( CPLCheckForFile( pszLocation, NULL) )
     336                 :         {//filesystem
     337               2 :             psSrcTree = CPLParseXMLFile( pszURL );
     338                 :         }
     339               3 :         else if( CPLHTTPEnabled() )
     340                 :         {//web resource
     341               3 :             CPLErrorReset();
     342               3 :             CPLHTTPResult *psResult = CPLHTTPFetch( pszURL, NULL );
     343               3 :             if( psResult != NULL )
     344                 :             {
     345               3 :                 if( psResult->nDataLen > 0 && CPLGetLastErrorNo() == 0)
     346               3 :                     psSrcTree = CPLParseXMLString( (const char*)psResult->pabyData );
     347               3 :                 CPLHTTPDestroyResult( psResult );
     348                 :             }
     349                 :         }
     350                 : 
     351                 :         //report error in case the resource cannot be retrieved.
     352               5 :         if( psSrcTree == NULL )
     353                 :             CPLError( CE_Failure, CPLE_NotSupported,
     354               0 :                       "Could not access %s", pszLocation );
     355                 : 
     356               5 :         CPLFree( pszLocation );
     357                 : 
     358                 : /************************************************************************/
     359                 : /*      In the external GML resource we will only need elements         */
     360                 : /*      identified by a "gml:id". So trim them.                         */
     361                 : /************************************************************************/
     362               5 :         psSibling = psSrcTree;
     363              20 :         while( psSibling != NULL )
     364                 :         {
     365              10 :             TrimTree( psSibling );
     366              10 :             psSibling = psSibling->psNext;
     367                 :         }
     368                 : 
     369                 :     //update to lists
     370               5 :         nItems = CSLCount(*ppapszResourceHREF);
     371               5 :         *ppapszResourceHREF = CSLAddString( *ppapszResourceHREF, pszURL );
     372                 :         *ppapsRoot = (CPLXMLNode**)CPLRealloc(*ppapsRoot,
     373               5 :                                             (nItems+2)*sizeof(CPLXMLNode*));
     374               5 :         (*ppapsRoot)[nItems] = psSrcTree;
     375               5 :         (*ppapsRoot)[nItems+1] = NULL;
     376                 : 
     377                 :     //return the tree
     378               5 :         return (*ppapsRoot)[nItems];
     379                 :     }
     380                 : }
     381                 : 
     382                 : /************************************************************************/
     383                 : /*                           ResolveTree()                              */
     384                 : /*  Resolves the xlinks in a node and it's siblings                     */
     385                 : /*  If any error is encountered or any element is skipped(papszSkip):   */
     386                 : /*      If bStrict is TRUE, process is stopped and CE_Error is returned */
     387                 : /*      If bStrict is FALSE, the process is continued but CE_Warning is */
     388                 : /*       returned at the end.                                           */
     389                 : /*  If everything goes fine, CE_None is returned.                       */
     390                 : /************************************************************************/
     391                 : 
     392           11015 : static CPLErr Resolve( CPLXMLNode * psNode,
     393                 :                 CPLXMLNode *** ppapsRoot,
     394                 :                 char *** ppapszResourceHREF,
     395                 :                 char ** papszSkip,
     396                 :                 const int bStrict )
     397                 : 
     398                 : {
     399                 :     //for each sibling
     400           11015 :     CPLXMLNode *psSibling = NULL;
     401           11015 :     CPLXMLNode *psResource = NULL;
     402           11015 :     CPLXMLNode *psTarget = NULL;
     403           11015 :     CPLErr eReturn = CE_None, eReturned;
     404                 :     
     405           29365 :     for( psSibling = psNode; psSibling != NULL; psSibling = psSibling->psNext )
     406                 :     {
     407           18350 :         if( psSibling->eType != CXT_Element )
     408            7016 :             continue;
     409                 : 
     410           11334 :         CPLXMLNode *psChild = psSibling->psChild;
     411           39778 :         while( psChild != NULL &&
     412                 :                !( psChild->eType == CXT_Attribute &&
     413                 :                   EQUAL( psChild->pszValue, "xlink:href" ) ) )
     414           17110 :             psChild = psChild->psNext;
     415                 : 
     416                 :         //if a child has a "xlink:href" attribute
     417           11334 :         if( psChild != NULL && psChild->psChild != NULL )
     418                 :         {
     419            1187 :             if( CSLFindString( papszSkip, psSibling->pszValue ) >= 0 )
     420                 :             {//Skipping a specified element
     421             324 :                 eReturn = CE_Warning;
     422             324 :                 continue;
     423                 :             }
     424                 : 
     425                 :             static int i = 0;
     426             863 :             if( i-- == 0 )
     427                 :             {//a way to track progress
     428               4 :                 i = 256;
     429                 :                 CPLDebug( "GML",
     430                 :                           "Resolving xlinks... (currently %s)",
     431               4 :                           psChild->psChild->pszValue );
     432                 :             }
     433                 : 
     434                 :             char **papszTokens;
     435                 :             papszTokens = CSLTokenizeString2( psChild->psChild->pszValue, "#",
     436                 :                                               CSLT_ALLOWEMPTYTOKENS |
     437                 :                                               CSLT_STRIPLEADSPACES |
     438             863 :                                               CSLT_STRIPENDSPACES );
     439             863 :             if( CSLCount( papszTokens ) != 2 || strlen(papszTokens[1]) <= 0 )
     440                 :             {
     441                 :                 CPLError( bStrict ? CE_Failure : CE_Warning,
     442                 :                           CPLE_NotSupported,
     443                 :                           "Error parsing the href %s.%s",
     444                 :                           psChild->psChild->pszValue,
     445               0 :                           bStrict ? "" : " Skipping..." );
     446               0 :                 CSLDestroy( papszTokens );
     447               0 :                 if( bStrict )
     448               0 :                     return CE_Failure;
     449               0 :                 eReturn = CE_Warning;
     450               0 :                 continue;
     451                 :             }
     452                 : 
     453                 :             //look for the resource with that URL
     454                 :             psResource = FindTreeByURL( ppapsRoot,
     455                 :                                         ppapszResourceHREF,
     456             863 :                                         papszTokens[0] );
     457             863 :             if( psResource == NULL )
     458                 :             {
     459               0 :                 CSLDestroy( papszTokens );
     460               0 :                 if( bStrict )
     461               0 :                     return CE_Failure;
     462               0 :                 eReturn = CE_Warning;
     463               0 :                 continue;
     464                 :             }
     465                 : 
     466                 :             //look for the element with the ID
     467             863 :             psTarget = FindElementByID( psResource, papszTokens[1] );
     468             863 :             if( psTarget != NULL )
     469                 :             {
     470                 :                 //remove the xlink:href attribute
     471             787 :                 CPLRemoveXMLChild( psSibling, psChild );
     472             787 :                 CPLDestroyXMLNode( psChild );
     473                 : 
     474                 :                 //make a copy of psTarget
     475                 :                 CPLXMLNode *psCopy = CPLCreateXMLNode( NULL,
     476                 :                                                        CXT_Element,
     477             787 :                                                        psTarget->pszValue );
     478             787 :                 psCopy->psChild = CPLCloneXMLTree( psTarget->psChild );
     479             787 :                 RemoveIDs( psCopy );
     480                 :                 //correct empty URLs in URL#id pairs
     481             787 :                 if( CPLStrnlen( papszTokens[0], 1 ) > 0 )
     482                 :                 {
     483             787 :                     CorrectURLs( psCopy, papszTokens[0] );
     484                 :                 }
     485             787 :                 CPLAddXMLChild( psSibling, psCopy );
     486             787 :                 CSLDestroy( papszTokens );
     487                 :             }
     488                 :             else
     489                 :             {
     490                 :                 //element not found
     491              76 :                 CSLDestroy( papszTokens );
     492                 :                 CPLError( bStrict ? CE_Failure : CE_Warning,
     493                 :                           CPLE_ObjectNull,
     494                 :                           "Couldn't find the element with id %s.",
     495              76 :                           psChild->psChild->pszValue );
     496              76 :                 if( bStrict )
     497               0 :                     return CE_Failure;
     498              76 :                 eReturn = CE_Warning;
     499                 :             }
     500                 :         }
     501                 : 
     502                 :         //Recurse with the first child
     503                 :         eReturned=Resolve( psSibling->psChild,
     504                 :                            ppapsRoot,
     505                 :                            ppapszResourceHREF,
     506                 :                            papszSkip,
     507           11010 :                            bStrict );
     508                 : 
     509           11010 :         if( eReturned == CE_Failure )
     510               0 :             return CE_Failure;
     511                 : 
     512           11010 :         if( eReturned == CE_Warning )
     513            1139 :                 eReturn = CE_Warning;
     514                 :     }
     515           11015 :     return eReturn;
     516                 : }
     517                 : 
     518                 : /************************************************************************/
     519                 : /*                           ResolveXlinks()                            */
     520                 : /*      Returns TRUE for success                                        */
     521                 : /*    - Returns CE_None for success,                                    */
     522                 : /*      CE_Warning if the resolved file is saved to a different file or */
     523                 : /*      CE_Failure if it could not be saved at all.                     */
     524                 : /*    - m_pszFilename will be set to the file the resolved file was     */
     525                 : /*      saved to.                                                       */
     526                 : /************************************************************************/
     527                 : 
     528               5 : int GMLReader::ResolveXlinks( const char *pszFile,
     529                 :                               int* pbOutIsTempFile,
     530                 :                               char **papszSkip,
     531                 :                               const int bStrict)
     532                 : 
     533                 : {
     534               5 :     *pbOutIsTempFile = FALSE;
     535                 : 
     536                 : // Check if the original source file is set.
     537               5 :     if( m_pszFilename == NULL )
     538                 :     {
     539                 :         CPLError( CE_Failure, CPLE_NotSupported,
     540                 :                   "GML source file needs to be set first with "
     541               0 :                   "GMLReader::SetSourceFile()." );
     542               0 :         return FALSE;
     543                 :     }
     544                 : 
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Load the raw XML file into a XML Node tree.                     */
     547                 : /* -------------------------------------------------------------------- */
     548                 :     CPLXMLNode **papsSrcTree;
     549               5 :     papsSrcTree = (CPLXMLNode **)CPLCalloc( 2, sizeof(CPLXMLNode *));
     550               5 :     papsSrcTree[0] = CPLParseXMLFile( m_pszFilename );
     551                 : 
     552               5 :     if( papsSrcTree[0] == NULL )
     553                 :     {
     554               0 :         CPLFree(papsSrcTree);
     555               0 :         return FALSE;
     556                 :     }
     557                 : 
     558                 :     //make all the URLs absolute
     559               5 :     CPLXMLNode *psSibling = NULL;
     560              15 :     for( psSibling = papsSrcTree[0]; psSibling != NULL; psSibling = psSibling->psNext )
     561              10 :         CorrectURLs( psSibling, m_pszFilename );
     562                 : 
     563                 :     //setup resource data structure
     564               5 :     char **papszResourceHREF = NULL;
     565                 :     // "" is the href of the original source file
     566               5 :     papszResourceHREF = CSLAddString( papszResourceHREF, m_pszFilename );
     567                 : 
     568                 :     //call resolver
     569               5 :     CPLErr eReturned = CE_None;
     570               5 :     eReturned = Resolve( papsSrcTree[0], &papsSrcTree, &papszResourceHREF, papszSkip, bStrict );
     571                 : 
     572               5 :     int bReturn = TRUE;
     573               5 :     if( eReturned != CE_Failure )
     574                 :     {
     575               5 :         char *pszTmpName = NULL;
     576               5 :         int bTryWithTempFile = FALSE;
     577               5 :         if( EQUALN(pszFile, "/vsitar/", strlen("/vsitar/")) ||
     578                 :             EQUALN(pszFile, "/vsigzip/", strlen("/vsigzip/")) ||
     579                 :             EQUALN(pszFile, "/vsizip/", strlen("/vsizip/")) )
     580                 :         {
     581               0 :             bTryWithTempFile = TRUE;
     582                 :         }
     583               5 :         else if( !CPLSerializeXMLTreeToFile( papsSrcTree[0], pszFile ) )
     584                 :         {
     585                 :             CPLError( CE_Failure, CPLE_FileIO,
     586                 :                       "Cannot serialize resolved file %s to %s.",
     587               0 :                       m_pszFilename, pszFile );
     588               0 :             bTryWithTempFile = TRUE;
     589                 :         }
     590                 : 
     591               5 :         if (bTryWithTempFile)
     592                 :         {
     593               0 :             pszTmpName = CPLStrdup( CPLGenerateTempFilename( "ResolvedGML" ) );
     594               0 :             if( !CPLSerializeXMLTreeToFile( papsSrcTree[0], pszTmpName ) )
     595                 :             {
     596                 :                 CPLError( CE_Failure, CPLE_FileIO,
     597                 :                           "Cannot serialize resolved file %s to %s either.",
     598               0 :                           m_pszFilename, pszTmpName );
     599               0 :                 CPLFree( pszTmpName );
     600               0 :                 bReturn = FALSE;
     601                 :             }
     602                 :             else
     603                 :             {
     604                 :             //set the source file to the resolved file
     605               0 :                 CPLFree( m_pszFilename );
     606               0 :                 m_pszFilename = pszTmpName;
     607               0 :                 *pbOutIsTempFile = TRUE;
     608                 :             }
     609                 :         }
     610                 :         else
     611                 :         {
     612                 :         //set the source file to the resolved file
     613               5 :             CPLFree( m_pszFilename );
     614               5 :             m_pszFilename = CPLStrdup( pszFile );
     615                 :         }
     616                 :     }
     617                 :     else
     618                 :     {
     619               0 :         bReturn = FALSE;
     620                 :     }
     621                 : 
     622               5 :     int nItems = CSLCount( papszResourceHREF );
     623               5 :     CSLDestroy( papszResourceHREF );
     624              20 :     while( nItems > 0 )
     625              10 :         CPLDestroyXMLNode( papsSrcTree[--nItems] );
     626               5 :     CPLFree( papsSrcTree );
     627                 : 
     628               5 :     return bReturn;
     629                 : }

Generated by: LCOV version 1.7