LCOV - code coverage report
Current view: directory - ogr - ogr_srs_xml.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 365 300 82.2 %
Date: 2010-01-09 Functions: 21 21 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_srs_xml.cpp 16587 2009-03-15 00:09:42Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  OGRSpatialReference interface to OGC XML (014r4).
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Frank Warmerdam (warmerdam@pobox.com)
      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_spatialref.h"
      31                 : #include "ogr_p.h"
      32                 : #include "cpl_minixml.h"
      33                 : #include "cpl_multiproc.h"
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                              parseURN()                              */
      37                 : /*                                                                      */
      38                 : /*      Parses requested sections out of URN.  The passed in URN        */
      39                 : /*      *is* altered but the returned values point into the             */
      40                 : /*      original string.                                                */
      41                 : /************************************************************************/
      42                 : 
      43               5 : static int parseURN( char *pszURN, 
      44                 :                      const char **ppszObjectType, 
      45                 :                      const char **ppszAuthority, 
      46                 :                      const char **ppszCode,
      47                 :                      const char **ppszVersion = NULL )
      48                 : 
      49                 : {
      50                 :     int  i;
      51                 : 
      52               5 :     if( ppszObjectType != NULL )
      53               0 :         *ppszObjectType = "";
      54               5 :     if( ppszAuthority != NULL )
      55               5 :         *ppszAuthority = "";
      56               5 :     if( ppszCode != NULL )
      57               5 :         *ppszCode = "";
      58               5 :     if( ppszVersion != NULL )
      59               0 :         *ppszVersion = "";
      60                 : 
      61                 : /* -------------------------------------------------------------------- */
      62                 : /*      Verify prefix.                                                  */
      63                 : /* -------------------------------------------------------------------- */
      64               5 :     if( !EQUALN(pszURN,"urn:ogc:def:",12) )
      65               0 :         return FALSE;
      66                 : 
      67                 : /* -------------------------------------------------------------------- */
      68                 : /*      Extract object type                                             */
      69                 : /* -------------------------------------------------------------------- */
      70               5 :     if( ppszObjectType != NULL )
      71               0 :         *ppszObjectType = (const char *) pszURN + 12;
      72                 : 
      73               5 :     i = 12;
      74              38 :     while( pszURN[i] != ':' && pszURN[i] != '\0' )
      75              28 :         i++;
      76                 : 
      77               5 :     if( pszURN[i] == '\0' )
      78               0 :         return FALSE;
      79                 : 
      80               5 :     pszURN[i] = '\0';
      81               5 :     i++;
      82                 : 
      83                 : /* -------------------------------------------------------------------- */
      84                 : /*      Extract authority                                               */
      85                 : /* -------------------------------------------------------------------- */
      86               5 :     if( ppszAuthority != NULL )
      87               5 :         *ppszAuthority = (char *) pszURN + i;
      88                 : 
      89              30 :     while( pszURN[i] != ':' && pszURN[i] != '\0' )
      90              20 :         i++;
      91                 : 
      92               5 :     if( pszURN[i] == '\0' )
      93               0 :         return FALSE;
      94                 : 
      95               5 :     pszURN[i] = '\0';
      96               5 :     i++;
      97                 : 
      98                 : /* -------------------------------------------------------------------- */
      99                 : /*      Extract version                                                 */
     100                 : /* -------------------------------------------------------------------- */
     101               5 :     if( ppszVersion != NULL )
     102               0 :         *ppszVersion = (char *) pszURN + i;
     103                 : 
     104              10 :     while( pszURN[i] != ':' && pszURN[i] != '\0' )
     105               0 :         i++;
     106                 : 
     107               5 :     if( pszURN[i] == '\0' )
     108               0 :         return FALSE;
     109                 : 
     110               5 :     pszURN[i] = '\0';
     111               5 :     i++;
     112                 : 
     113                 : /* -------------------------------------------------------------------- */
     114                 : /*      Extract code.                                                   */
     115                 : /* -------------------------------------------------------------------- */
     116               5 :     if( ppszCode != NULL )
     117               5 :         *ppszCode = (char *) pszURN + i;
     118                 :     
     119               5 :     return TRUE;
     120                 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                               addURN()                               */
     124                 : /************************************************************************/
     125                 : 
     126               6 : static void addURN( CPLXMLNode *psTarget, 
     127                 :                     const char *pszAuthority, 
     128                 :                     const char *pszObjectType, 
     129                 :                     int nCode,
     130                 :                     const char *pszVersion = "" )
     131                 : 
     132                 : {
     133                 :     char szURN[200];
     134                 : 
     135               6 :     if( pszVersion == NULL )
     136               0 :         pszVersion = "";
     137                 : 
     138                 :     CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
     139                 : 
     140                 :     sprintf( szURN, "urn:ogc:def:%s:%s:%s:", 
     141               6 :              pszObjectType, pszAuthority, pszVersion );
     142                 :     
     143               6 :     if( nCode != 0 )
     144               6 :         sprintf( szURN + strlen(szURN), "%d", nCode );
     145                 :     
     146                 :     CPLCreateXMLNode(
     147                 :         CPLCreateXMLNode( psTarget, CXT_Attribute, "xlink:href" ),
     148               6 :         CXT_Text, szURN );
     149               6 : }
     150                 : 
     151                 : /************************************************************************/
     152                 : /*                         AddValueIDWithURN()                          */
     153                 : /*                                                                      */
     154                 : /*      Adds element of the form <ElementName                           */
     155                 : /*      xlink:href="urn_without_id">id</ElementName>"                   */
     156                 : /************************************************************************/
     157                 : 
     158                 : static CPLXMLNode *
     159               6 : AddValueIDWithURN( CPLXMLNode *psTarget, 
     160                 :                    const char *pszElement,
     161                 :                    const char *pszAuthority, 
     162                 :                    const char *pszObjectType, 
     163                 :                    int nCode,
     164                 :                    const char *pszVersion = "" )
     165                 :     
     166                 : {
     167                 :     CPLXMLNode *psElement;
     168                 : 
     169               6 :     psElement = CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
     170               6 :     addURN( psElement, pszAuthority, pszObjectType, nCode, pszVersion );
     171                 : 
     172               6 :     return psElement;
     173                 : }
     174                 : 
     175                 : /************************************************************************/
     176                 : /*                          addAuthorityIDBlock()                          */
     177                 : /*                                                                      */
     178                 : /*      Creates a structure like:                                       */
     179                 : /*      <srsId>                                                         */
     180                 : /*        <name codeSpace="urn">code</name>                             */
     181                 : /*      </srsId>                                                        */
     182                 : /************************************************************************/
     183              11 : static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget, 
     184                 :                                      const char *pszElement,
     185                 :                                      const char *pszAuthority, 
     186                 :                                      const char *pszObjectType, 
     187                 :                                      int nCode,
     188                 :                                      const char *pszVersion = "" )
     189                 : 
     190                 : {
     191                 :     char szURN[200];
     192                 : 
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      Prepare partial URN without the actual code.                    */
     195                 : /* -------------------------------------------------------------------- */
     196              11 :     if( pszVersion == NULL )
     197               5 :         pszVersion = "";
     198                 : 
     199                 :     CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
     200                 : 
     201                 :     sprintf( szURN, "urn:ogc:def:%s:%s:%s:", 
     202              11 :              pszObjectType, pszAuthority, pszVersion );
     203                 :     
     204                 : /* -------------------------------------------------------------------- */
     205                 : /*      Prepare the base name, eg. <srsID>.                             */
     206                 : /* -------------------------------------------------------------------- */
     207                 :     CPLXMLNode *psElement = 
     208              11 :         CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
     209                 : 
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      Prepare the name element.                                       */
     212                 : /* -------------------------------------------------------------------- */
     213                 :     CPLXMLNode * psName = 
     214              11 :         CPLCreateXMLNode( psElement, CXT_Element, "gml:name" );
     215                 : 
     216                 : /* -------------------------------------------------------------------- */
     217                 : /*      Prepare the codespace attribute.                                */
     218                 : /* -------------------------------------------------------------------- */
     219                 :     CPLCreateXMLNode(
     220                 :         CPLCreateXMLNode( psName, CXT_Attribute, "gml:codeSpace" ),
     221              11 :         CXT_Text, szURN );
     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      Attach code value to name node.                                 */
     225                 : /* -------------------------------------------------------------------- */
     226                 :     char szCode[32];
     227              11 :     sprintf( szCode, "%d", nCode );
     228                 : 
     229              11 :     CPLCreateXMLNode( psName, CXT_Text, szCode );
     230                 : 
     231              11 :     return psElement;
     232                 : }
     233                 :     
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                              addGMLId()                              */
     237                 : /************************************************************************/
     238                 : 
     239              12 : static void addGMLId( CPLXMLNode *psParent )
     240                 : 
     241                 : {
     242                 :     static void *hGMLIdMutex = NULL;
     243              12 :     CPLMutexHolderD( &hGMLIdMutex );
     244                 : 
     245                 :     CPLXMLNode *psId;
     246                 :     static int nNextGMLId = 1;
     247                 :     char   szIdText[40];
     248                 : 
     249              12 :     sprintf( szIdText, "ogrcrs%d", nNextGMLId++ );
     250                 :     
     251                 :     psId = 
     252                 :         CPLCreateXMLNode( 
     253                 :             CPLCreateXMLNode( psParent, CXT_Attribute, "gml:id" ),
     254              12 :             CXT_Text, szIdText );
     255              12 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /*                        exportAuthorityToXML()                        */
     259                 : /************************************************************************/
     260                 : 
     261               5 : static CPLXMLNode *exportAuthorityToXML( const OGR_SRSNode *poAuthParent,
     262                 :                                          const char *pszTagName,
     263                 :                                          CPLXMLNode *psXMLParent,
     264                 :                                          const char *pszObjectType,
     265                 :                                          int bUseSubName = TRUE )
     266                 : 
     267                 : {
     268                 :     const OGR_SRSNode *poAuthority;
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Get authority node from parent.                                 */
     272                 : /* -------------------------------------------------------------------- */
     273               5 :     if( poAuthParent->FindChild( "AUTHORITY" ) == -1 )
     274               0 :         return NULL;
     275                 : 
     276                 :     poAuthority = poAuthParent->GetChild( 
     277               5 :         poAuthParent->FindChild( "AUTHORITY" ));
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*      Create identification.                                          */
     281                 : /* -------------------------------------------------------------------- */
     282                 :     const char *pszCode, *pszCodeSpace, *pszEdition;
     283                 : 
     284               5 :     pszCode = poAuthority->GetChild(1)->GetValue();
     285               5 :     pszCodeSpace = poAuthority->GetChild(0)->GetValue();
     286               5 :     pszEdition = NULL;
     287                 : 
     288               5 :     if( bUseSubName )
     289                 :         return addAuthorityIDBlock( psXMLParent, pszTagName, pszCodeSpace, 
     290               5 :                                  pszObjectType, atoi(pszCode), pszEdition );
     291                 :     else
     292                 :         return AddValueIDWithURN( psXMLParent, pszTagName, pszCodeSpace, 
     293               0 :                                   pszObjectType, atoi(pszCode), pszEdition );
     294                 :                               
     295                 : }
     296                 : 
     297                 : /************************************************************************/
     298                 : /*                             addProjArg()                             */
     299                 : /************************************************************************/
     300                 : 
     301               5 : static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase, 
     302                 :                         const char *pszMeasureType, double dfDefault,
     303                 :                         int nParameterID, const char *pszWKTName )
     304                 : 
     305                 : {
     306                 :     CPLXMLNode *psNode, *psValue;
     307                 : 
     308               5 :     psNode = CPLCreateXMLNode( psBase, CXT_Element, "gml:usesParameterValue" );
     309                 : 
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Handle the UOM.                                                 */
     312                 : /* -------------------------------------------------------------------- */
     313                 :     const char *pszUOMValue;
     314                 : 
     315               5 :     if( EQUAL(pszMeasureType,"Angular") )
     316               2 :         pszUOMValue = "urn:ogc:def:uom:EPSG::9102";
     317                 :     else
     318               3 :         pszUOMValue = "urn:ogc:def:uom:EPSG::9001";
     319                 : 
     320               5 :     psValue = CPLCreateXMLNode( psNode, CXT_Element, "gml:value" );
     321                 : 
     322                 :     CPLCreateXMLNode( 
     323                 :         CPLCreateXMLNode( psValue, CXT_Attribute, "gml:uom" ),
     324               5 :         CXT_Text, pszUOMValue );
     325                 :     
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      Add the parameter value itself.                                 */
     328                 : /* -------------------------------------------------------------------- */
     329                 :     double dfParmValue
     330               5 :         = poSRS->GetNormProjParm( pszWKTName, dfDefault, NULL );
     331                 :         
     332                 :     CPLCreateXMLNode( psValue, CXT_Text, 
     333               5 :                       CPLString().Printf( "%.16g", dfParmValue ) );
     334                 : 
     335                 : /* -------------------------------------------------------------------- */
     336                 : /*      Add the valueOfParameter.                                       */
     337                 : /* -------------------------------------------------------------------- */
     338                 :     AddValueIDWithURN( psNode, "gml:valueOfParameter", "EPSG", "parameter", 
     339               5 :                        nParameterID );
     340               5 : }
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                              addAxis()                               */
     344                 : /*                                                                      */
     345                 : /*      Added the <usesAxis> element and down.                          */
     346                 : /************************************************************************/
     347                 : 
     348               4 : static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent, 
     349                 :                             const char *pszAxis, // "Lat", "Long", "E" or "N"
     350                 :                             const OGR_SRSNode * /* poUnitsSrc */ )
     351                 : 
     352                 : {
     353                 :     CPLXMLNode *psAxisXML;
     354                 : 
     355                 :     psAxisXML = 
     356                 :         CPLCreateXMLNode( 
     357                 :             CPLCreateXMLNode( psXMLParent, CXT_Element, "gml:usesAxis" ),
     358               4 :             CXT_Element, "gml:CoordinateSystemAxis" );
     359               4 :     addGMLId( psAxisXML );
     360                 : 
     361               4 :     if( EQUAL(pszAxis,"Lat") )
     362                 :     {
     363                 :         CPLCreateXMLNode( 
     364                 :             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
     365               1 :             CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
     366                 : 
     367                 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:name",
     368               1 :                                      "Geodetic latitude" );
     369               1 :         addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9901 );
     370               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lat" );
     371               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
     372                 :     }
     373               3 :     else if( EQUAL(pszAxis,"Long") )
     374                 :     {
     375                 :         CPLCreateXMLNode( 
     376                 :             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
     377               1 :             CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
     378                 : 
     379                 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:name",
     380               1 :                                      "Geodetic longitude" );
     381               1 :         addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9902 );
     382               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lon" );
     383               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
     384                 :     }
     385               2 :     else if( EQUAL(pszAxis,"E") )
     386                 :     {
     387                 :         CPLCreateXMLNode( 
     388                 :             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
     389               1 :             CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
     390                 : 
     391               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:name", "Easting" );
     392               1 :         addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9906 );
     393               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "E" );
     394               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
     395                 :     }
     396               1 :     else if( EQUAL(pszAxis,"N") )
     397                 :     {
     398                 :         CPLCreateXMLNode( 
     399                 :             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
     400               1 :             CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
     401                 : 
     402               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:name", "Northing" );
     403               1 :         addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9907 );
     404               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "N" );
     405               1 :         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
     406                 :     }
     407                 :     else
     408                 :     {
     409                 :         CPLAssert( FALSE );
     410                 :     }
     411                 : 
     412               4 :     return psAxisXML;
     413                 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                         exportGeogCSToXML()                          */
     417                 : /************************************************************************/
     418                 : 
     419               1 : static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
     420                 : 
     421                 : {
     422                 :     CPLXMLNode  *psGCS_XML;
     423               1 :     const OGR_SRSNode *poGeogCS = poSRS->GetAttrNode( "GEOGCS" );
     424                 : 
     425               1 :     if( poGeogCS == NULL )
     426               0 :         return NULL;
     427                 :     
     428                 : /* -------------------------------------------------------------------- */
     429                 : /*      Establish initial infrastructure.                               */
     430                 : /* -------------------------------------------------------------------- */
     431               1 :     psGCS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
     432               1 :     addGMLId( psGCS_XML );
     433                 :     
     434                 : /* -------------------------------------------------------------------- */
     435                 : /*      Attach symbolic name (srsName).                                 */
     436                 : /* -------------------------------------------------------------------- */
     437                 :     CPLCreateXMLElementAndValue( psGCS_XML, "gml:srsName", 
     438               1 :                                  poGeogCS->GetChild(0)->GetValue() );
     439                 : 
     440                 : /* -------------------------------------------------------------------- */
     441                 : /*      Does the overall coordinate system have an authority?  If so    */
     442                 : /*      attach as an identification section.                            */
     443                 : /* -------------------------------------------------------------------- */
     444               1 :     exportAuthorityToXML( poGeogCS, "gml:srsID", psGCS_XML, "crs" );
     445                 : 
     446                 : /* -------------------------------------------------------------------- */
     447                 : /*      Insert a big whack of fixed stuff defining the                  */
     448                 : /*      ellipsoidalCS.  Basically this defines the axes and their       */
     449                 : /*      units.                                                          */
     450                 : /* -------------------------------------------------------------------- */
     451                 :     CPLXMLNode *psECS;
     452                 : 
     453                 :     psECS = CPLCreateXMLNode( 
     454                 :         CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesEllipsoidalCS" ),
     455               1 :         CXT_Element, "gml:EllipsoidalCS" );
     456                 : 
     457               1 :     addGMLId( psECS  );
     458                 : 
     459               1 :     CPLCreateXMLElementAndValue( psECS, "gml:csName", "ellipsoidal" );
     460                 : 
     461               1 :     addAuthorityIDBlock( psECS, "gml:csID", "EPSG", "cs", 6402 );
     462                 : 
     463               1 :     addAxis( psECS, "Lat", NULL );
     464               1 :     addAxis( psECS, "Long", NULL );
     465                 : 
     466                 : /* -------------------------------------------------------------------- */
     467                 : /*      Start with the datum.                                           */
     468                 : /* -------------------------------------------------------------------- */
     469               1 :     const OGR_SRSNode    *poDatum = poGeogCS->GetNode( "DATUM" );
     470                 :     CPLXMLNode     *psDatumXML;
     471                 : 
     472               1 :     if( poDatum == NULL )
     473                 :     {
     474               0 :         CPLDestroyXMLNode( psGCS_XML );
     475               0 :         return NULL;
     476                 :     }
     477                 : 
     478                 :     psDatumXML = CPLCreateXMLNode( 
     479                 :         CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesGeodeticDatum" ),
     480               1 :         CXT_Element, "gml:GeodeticDatum" );
     481                 :     
     482               1 :     addGMLId( psDatumXML );
     483                 : 
     484                 : /* -------------------------------------------------------------------- */
     485                 : /*      Set the datumName.                                              */
     486                 : /* -------------------------------------------------------------------- */
     487                 :     CPLCreateXMLElementAndValue( psDatumXML, "gml:datumName", 
     488               1 :                                  poDatum->GetChild(0)->GetValue() );
     489                 : 
     490                 : /* -------------------------------------------------------------------- */
     491                 : /*      Set authority id info if available.                             */
     492                 : /* -------------------------------------------------------------------- */
     493               1 :     exportAuthorityToXML( poDatum, "gml:datumID", psDatumXML, "datum" );
     494                 : 
     495                 : /* -------------------------------------------------------------------- */
     496                 : /*      Setup prime meridian information.                               */
     497                 : /* -------------------------------------------------------------------- */
     498               1 :     const OGR_SRSNode *poPMNode = poGeogCS->GetNode( "PRIMEM" );
     499                 :     CPLXMLNode *psPM;
     500               1 :     char *pszPMName = (char* ) "Greenwich";
     501               1 :     double dfPMOffset = poSRS->GetPrimeMeridian( &pszPMName );
     502                 : 
     503                 :     psPM = CPLCreateXMLNode( 
     504                 :         CPLCreateXMLNode( psDatumXML, CXT_Element, "gml:usesPrimeMeridian" ),
     505               1 :         CXT_Element, "gml:PrimeMeridian" );
     506                 : 
     507               1 :     addGMLId( psPM );
     508                 : 
     509               1 :     CPLCreateXMLElementAndValue( psPM, "gml:meridianName", pszPMName );
     510                 : 
     511               1 :     if( poPMNode )
     512               1 :         exportAuthorityToXML( poPMNode, "gml:meridianID", psPM, "meridian" );
     513                 : 
     514                 :     CPLXMLNode *psAngle;
     515                 : 
     516                 :     psAngle = 
     517                 :         CPLCreateXMLNode( 
     518                 :             CPLCreateXMLNode( psPM, CXT_Element, "gml:greenwichLongitude" ),
     519               1 :             CXT_Element, "gml:angle" );
     520                 :     
     521                 :     CPLCreateXMLNode( CPLCreateXMLNode( psAngle, CXT_Attribute, "gml:uom" ),
     522               1 :                       CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
     523                 : 
     524                 :     CPLCreateXMLNode( psAngle, CXT_Text, 
     525               1 :                       CPLString().Printf( "%.16g", dfPMOffset ) );
     526                 :     
     527                 : /* -------------------------------------------------------------------- */
     528                 : /*      Translate the ellipsoid.                                        */
     529                 : /* -------------------------------------------------------------------- */
     530               1 :     const OGR_SRSNode *poEllipsoid = poDatum->GetNode( "SPHEROID" );
     531                 : 
     532               1 :     if( poEllipsoid != NULL )
     533                 :     {
     534                 :         CPLXMLNode *psEllipseXML;
     535                 : 
     536                 :         psEllipseXML = 
     537                 :             CPLCreateXMLNode( 
     538                 :                 CPLCreateXMLNode(psDatumXML,CXT_Element,"gml:usesEllipsoid" ),
     539               1 :                 CXT_Element, "gml:Ellipsoid" );
     540                 : 
     541               1 :         addGMLId( psEllipseXML );
     542                 : 
     543                 :         CPLCreateXMLElementAndValue( psEllipseXML, "gml:ellipsoidName", 
     544               1 :                                      poEllipsoid->GetChild(0)->GetValue() );
     545                 : 
     546                 :         exportAuthorityToXML( poEllipsoid, "gml:ellipsoidID", psEllipseXML,
     547               1 :                               "ellipsoid");
     548                 :         
     549                 :         CPLXMLNode *psParmXML;
     550                 : 
     551                 :         psParmXML = CPLCreateXMLNode( psEllipseXML, CXT_Element, 
     552               1 :                                       "gml:semiMajorAxis" );
     553                 : 
     554                 :         CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"gml:uom"),
     555               1 :                           CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
     556                 : 
     557                 :         CPLCreateXMLNode( psParmXML, CXT_Text, 
     558               1 :                           poEllipsoid->GetChild(1)->GetValue() );
     559                 : 
     560                 :         psParmXML = 
     561                 :             CPLCreateXMLNode( 
     562                 :                 CPLCreateXMLNode( psEllipseXML, CXT_Element, 
     563                 :                                   "gml:secondDefiningParameter" ),
     564               1 :                 CXT_Element, "gml:inverseFlattening" );
     565                 :         
     566                 :         CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"gml:uom"),
     567               1 :                           CXT_Text, "urn:ogc:def:uom:EPSG::9201" );
     568                 : 
     569                 :         CPLCreateXMLNode( psParmXML, CXT_Text, 
     570               1 :                           poEllipsoid->GetChild(2)->GetValue() );
     571                 :     }
     572                 : 
     573               1 :     return psGCS_XML;
     574                 : }
     575                 : 
     576                 : /************************************************************************/
     577                 : /*                         exportProjCSToXML()                          */
     578                 : /************************************************************************/
     579                 : 
     580               1 : static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
     581                 : 
     582                 : {
     583               1 :     const OGR_SRSNode *poProjCS = poSRS->GetAttrNode( "PROJCS" );
     584                 : 
     585               1 :     if( poProjCS == NULL )
     586               0 :         return NULL;
     587                 :     
     588                 : /* -------------------------------------------------------------------- */
     589                 : /*      Establish initial infrastructure.                               */
     590                 : /* -------------------------------------------------------------------- */
     591                 :     CPLXMLNode   *psCRS_XML;
     592                 : 
     593               1 :     psCRS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
     594               1 :     addGMLId( psCRS_XML );
     595                 :     
     596                 : /* -------------------------------------------------------------------- */
     597                 : /*      Attach symbolic name (a name in a nameset).                     */
     598                 : /* -------------------------------------------------------------------- */
     599                 :     CPLCreateXMLElementAndValue( psCRS_XML, "gml:srsName", 
     600               1 :                                  poProjCS->GetChild(0)->GetValue() );
     601                 : 
     602                 : /* -------------------------------------------------------------------- */
     603                 : /*      Add authority info if we have it.                               */
     604                 : /* -------------------------------------------------------------------- */
     605               1 :     exportAuthorityToXML( poProjCS, "gml:srsID", psCRS_XML, "crs" );
     606                 : 
     607                 : /* -------------------------------------------------------------------- */
     608                 : /*      Use the GEOGCS as a <baseCRS>                                   */
     609                 : /* -------------------------------------------------------------------- */
     610                 :     CPLXMLNode *psBaseCRSXML =
     611               1 :         CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:baseCRS" );
     612                 : 
     613               1 :     CPLAddXMLChild( psBaseCRSXML, exportGeogCSToXML( poSRS ) );
     614                 : 
     615                 : /* -------------------------------------------------------------------- */
     616                 : /*      Our projected coordinate system is "defined by Conversion".     */
     617                 : /* -------------------------------------------------------------------- */
     618                 :     CPLXMLNode *psDefinedBy;
     619                 : 
     620                 :     psDefinedBy = CPLCreateXMLNode( psCRS_XML, CXT_Element, 
     621               1 :                                     "gml:definedByConversion" );
     622                 :     
     623                 : /* -------------------------------------------------------------------- */
     624                 : /*      Projections are handled as ParameterizedTransformations.        */
     625                 : /* -------------------------------------------------------------------- */
     626               1 :     const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
     627                 :     CPLXMLNode *psConv;
     628                 : 
     629               1 :     psConv = CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
     630               1 :     addGMLId( psConv );
     631                 : 
     632                 : /* -------------------------------------------------------------------- */
     633                 : /*      Transverse Mercator                                             */
     634                 : /* -------------------------------------------------------------------- */
     635               1 :     if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
     636                 :     {
     637                 :         AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method", 
     638               1 :                            9807 );
     639                 : 
     640                 :         addProjArg( poSRS, psConv, "Angular", 0.0,
     641               1 :                     8801, SRS_PP_LATITUDE_OF_ORIGIN );
     642                 :         addProjArg( poSRS, psConv, "Angular", 0.0,
     643               1 :                     8802, SRS_PP_CENTRAL_MERIDIAN );
     644                 :         addProjArg( poSRS, psConv, "Unitless", 1.0,
     645               1 :                     8805, SRS_PP_SCALE_FACTOR );
     646                 :         addProjArg( poSRS, psConv, "Linear", 0.0,
     647               1 :                     8806, SRS_PP_FALSE_EASTING );
     648                 :         addProjArg( poSRS, psConv, "Linear", 0.0,
     649               1 :                     8807, SRS_PP_FALSE_NORTHING );
     650                 :     }
     651                 : 
     652                 : /* -------------------------------------------------------------------- */
     653                 : /*      Lambert Conformal Conic                                         */
     654                 : /* -------------------------------------------------------------------- */
     655               0 :     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     656                 :     {
     657                 :         AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method", 
     658               0 :                            9801 );
     659                 : 
     660                 :         addProjArg( poSRS, psConv, "Angular", 0.0,
     661               0 :                     8801, SRS_PP_LATITUDE_OF_ORIGIN );
     662                 :         addProjArg( poSRS, psConv, "Angular", 0.0,
     663               0 :                     8802, SRS_PP_CENTRAL_MERIDIAN );
     664                 :         addProjArg( poSRS, psConv, "Unitless", 1.0,
     665               0 :                     8805, SRS_PP_SCALE_FACTOR );
     666                 :         addProjArg( poSRS, psConv, "Linear", 0.0,
     667               0 :                     8806, SRS_PP_FALSE_EASTING );
     668                 :         addProjArg( poSRS, psConv, "Linear", 0.0,
     669               0 :                     8807, SRS_PP_FALSE_NORTHING );
     670                 :     }
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Define the cartesian coordinate system.                         */
     674                 : /* -------------------------------------------------------------------- */
     675                 :     CPLXMLNode  *psCCS;
     676                 : 
     677                 :     psCCS = 
     678                 :         CPLCreateXMLNode( 
     679                 :             CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:usesCartesianCS" ),
     680               1 :             CXT_Element, "gml:CartesianCS" );
     681                 : 
     682               1 :     addGMLId( psCCS );
     683                 : 
     684               1 :     CPLCreateXMLElementAndValue( psCCS, "gml:csName", "Cartesian" );
     685               1 :     addAuthorityIDBlock( psCCS, "gml:csID", "EPSG", "cs", 4400 );
     686               1 :     addAxis( psCCS, "E", NULL );
     687               1 :     addAxis( psCCS, "N", NULL );
     688                 : 
     689               1 :     return psCRS_XML;
     690                 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                            exportToXML()                             */
     694                 : /************************************************************************/
     695                 : 
     696                 : /**
     697                 :  * \brief Export coordinate system in XML format.
     698                 :  *
     699                 :  * Converts the loaded coordinate reference system into XML format
     700                 :  * to the extent possible.  The string returned in ppszRawXML should be
     701                 :  * deallocated by the caller with CPLFree() when no longer needed.
     702                 :  *
     703                 :  * LOCAL_CS coordinate systems are not translatable.  An empty string
     704                 :  * will be returned along with OGRERR_NONE.  
     705                 :  *
     706                 :  * This method is the equivelent of the C function OSRExportToXML().
     707                 :  *
     708                 :  * @param ppszRawXML pointer to which dynamically allocated XML definition 
     709                 :  * will be assigned. 
     710                 :  * @param pszDialect currently ignored. The dialect used is GML based.
     711                 :  *
     712                 :  * @return OGRERR_NONE on success or an error code on failure. 
     713                 :  */
     714                 : 
     715               1 : OGRErr OGRSpatialReference::exportToXML( char **ppszRawXML, 
     716                 :                                          const char * pszDialect ) const
     717                 : 
     718                 : {
     719               1 :     CPLXMLNode *psXMLTree = NULL;
     720                 : 
     721               1 :     if( IsGeographic() )
     722                 :     {
     723               0 :         psXMLTree = exportGeogCSToXML( this );
     724                 :     }
     725               1 :     else if( IsProjected() )
     726                 :     {
     727               1 :         psXMLTree = exportProjCSToXML( this );
     728                 :     }
     729                 :     else
     730               0 :         return OGRERR_UNSUPPORTED_SRS;
     731                 : 
     732               1 :     *ppszRawXML = CPLSerializeXMLTree( psXMLTree );
     733               1 :     CPLDestroyXMLNode( psXMLTree );
     734                 : 
     735               1 :     return OGRERR_NONE;
     736                 : }
     737                 : 
     738                 : /************************************************************************/
     739                 : /*                           OSRExportToXML()                           */
     740                 : /************************************************************************/
     741                 : /** 
     742                 :  * \brief Export coordinate system in XML format.
     743                 :  *
     744                 :  * This function is the same as OGRSpatialReference::exportToXML().
     745                 :  */
     746                 : 
     747               1 : OGRErr OSRExportToXML( OGRSpatialReferenceH hSRS, char **ppszRawXML, 
     748                 :                        const char *pszDialect )
     749                 : 
     750                 : {
     751               1 :     VALIDATE_POINTER1( hSRS, "OSRExportToXML", CE_Failure );
     752                 : 
     753                 :     return ((OGRSpatialReference *) hSRS)->exportToXML( ppszRawXML, 
     754               1 :                                                         pszDialect );
     755                 : }
     756                 : 
     757                 : #ifdef notdef
     758                 : /************************************************************************/
     759                 : /*                           importXMLUnits()                           */
     760                 : /************************************************************************/
     761                 : 
     762                 : static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
     763                 :                             OGRSpatialReference *poSRS, const char *pszTarget)
     764                 : 
     765                 : {
     766                 :     const char *pszUnitName, *pszUnitsPer;
     767                 :     OGR_SRSNode *poNode = poSRS->GetAttrNode( pszTarget );
     768                 :     OGR_SRSNode *poUnits;
     769                 : 
     770                 :     CPLAssert( EQUAL(pszClass,"AngularUnit") 
     771                 :                || EQUAL(pszClass,"LinearUnit") );
     772                 :         
     773                 :     psSrcXML = CPLGetXMLNode( psSrcXML, pszClass );
     774                 :     if( psSrcXML == NULL )
     775                 :         goto DefaultTarget;
     776                 : 
     777                 :     pszUnitName = CPLGetXMLValue( psSrcXML, "NameSet.name", "unnamed" );
     778                 :     if( EQUAL(pszClass,"AngularUnit") )
     779                 :         pszUnitsPer = CPLGetXMLValue( psSrcXML, "radiansPerUnit", NULL );
     780                 :     else
     781                 :         pszUnitsPer = CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
     782                 :     
     783                 :     if( pszUnitsPer == NULL )
     784                 :     {
     785                 :         CPLDebug( "OGR_SRS_XML", 
     786                 :                   "Missing PerUnit value for %s.", 
     787                 :                   pszClass );
     788                 :         goto DefaultTarget;
     789                 :     }
     790                 :     
     791                 :     if( poNode == NULL )
     792                 :     {
     793                 :         CPLDebug( "OGR_SRS_XML", "Can't find %s in importXMLUnits.", 
     794                 :                   pszTarget );
     795                 :         goto DefaultTarget;
     796                 :     }
     797                 : 
     798                 :     if( poNode->FindChild("UNIT") != -1 )
     799                 :     {
     800                 :         poUnits = poNode->GetChild( poNode->FindChild( "UNIT" ) );
     801                 :         poUnits->GetChild(0)->SetValue( pszUnitName );
     802                 :         poUnits->GetChild(1)->SetValue( pszUnitsPer );
     803                 :     }
     804                 :     else
     805                 :     {
     806                 :         poUnits = new OGR_SRSNode( "UNIT" );
     807                 :         poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
     808                 :         poUnits->AddChild( new OGR_SRSNode( pszUnitsPer ) );
     809                 :         
     810                 :         poNode->AddChild( poUnits );
     811                 :     }
     812                 :     return;
     813                 : 
     814                 :   DefaultTarget:
     815                 :     poUnits = new OGR_SRSNode( "UNIT" );
     816                 :     if( EQUAL(pszClass,"AngularUnit") )
     817                 :     {
     818                 :         poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE ) );
     819                 :         poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE_CONV ) );
     820                 :     }
     821                 :     else
     822                 :     {
     823                 :         poUnits->AddChild( new OGR_SRSNode( SRS_UL_METER ) );
     824                 :         poUnits->AddChild( new OGR_SRSNode( "1.0" ) );
     825                 :     }
     826                 : 
     827                 :     poNode->AddChild( poUnits );
     828                 : }
     829                 : #endif
     830                 : 
     831                 : /************************************************************************/
     832                 : /*                         importXMLAuthority()                         */
     833                 : /************************************************************************/
     834                 : 
     835               5 : static void importXMLAuthority( CPLXMLNode *psSrcXML, 
     836                 :                                 OGRSpatialReference *poSRS, 
     837                 :                                 const char *pszSourceKey,
     838                 :                                 const char *pszTargetKey )
     839                 : 
     840                 : {
     841               5 :     CPLXMLNode *psIDNode = CPLGetXMLNode( psSrcXML, pszSourceKey );
     842               5 :     CPLXMLNode *psNameNode = CPLGetXMLNode( psIDNode, "name" );
     843               5 :     CPLXMLNode *psCodeSpace = CPLGetXMLNode( psNameNode, "codeSpace" );
     844                 :     const char *pszAuthority, *pszCode;
     845                 :     char *pszURN;
     846               5 :     int nCode = 0;
     847                 : 
     848               5 :     if( psIDNode == NULL || psNameNode == NULL || psCodeSpace == NULL )
     849               0 :         return;
     850                 : 
     851               5 :     pszURN = CPLStrdup(CPLGetXMLValue( psCodeSpace, "", "" ));
     852               5 :     if( !parseURN( pszURN, NULL, &pszAuthority, &pszCode ) )
     853                 :     {
     854               0 :         CPLFree( pszURN );
     855               0 :         return;
     856                 :     }
     857                 : 
     858               5 :     if( strlen(pszCode) == 0 )
     859               5 :         pszCode = (char *) CPLGetXMLValue( psNameNode, "", "" );
     860                 : 
     861               5 :     if( pszCode != NULL )
     862               5 :         nCode = atoi(pszCode);
     863                 : 
     864               5 :     if( nCode != 0 )
     865               5 :         poSRS->SetAuthority( pszTargetKey, pszAuthority, nCode );
     866                 : 
     867               5 :     CPLFree( pszURN );
     868                 : }
     869                 : 
     870                 : /************************************************************************/
     871                 : /*                           ParseOGCDefURN()                           */
     872                 : /*                                                                      */
     873                 : /*      Parse out fields from a URN of the form:                        */
     874                 : /*        urn:ogc:def:parameter:EPSG:6.3:9707                           */
     875                 : /************************************************************************/
     876                 : 
     877              16 : static int ParseOGCDefURN( const char *pszURN, 
     878                 :                            CPLString *poObjectType,
     879                 :                            CPLString *poAuthority,
     880                 :                            CPLString *poVersion, 
     881                 :                            CPLString *poValue )
     882                 : 
     883                 : {
     884              16 :     if( poObjectType != NULL )
     885              16 :         *poObjectType = "";
     886                 : 
     887              16 :     if( poAuthority != NULL )
     888              16 :         *poAuthority = "";
     889                 : 
     890              16 :     if( poVersion != NULL )
     891               0 :         *poVersion = "";
     892                 : 
     893              16 :     if( poValue != NULL )
     894              16 :         *poValue = "";
     895                 : 
     896              16 :     if( pszURN == NULL || !EQUALN(pszURN,"urn:ogc:def:",12) )
     897               0 :         return FALSE;
     898                 : 
     899                 :     char **papszTokens = CSLTokenizeStringComplex( pszURN + 12, ":", 
     900              16 :                                                    FALSE, TRUE );
     901                 : 
     902              16 :     if( CSLCount(papszTokens) != 4 )
     903                 :     {
     904               0 :         CSLDestroy( papszTokens );
     905               0 :         return FALSE;
     906                 :     }
     907                 : 
     908              16 :     if( poObjectType != NULL )
     909              16 :         *poObjectType = papszTokens[0];
     910                 : 
     911              16 :     if( poAuthority != NULL )
     912              16 :         *poAuthority = papszTokens[1];
     913                 : 
     914              16 :     if( poVersion != NULL )
     915               0 :         *poVersion = papszTokens[2];
     916                 : 
     917              16 :     if( poValue != NULL )
     918              16 :         *poValue = papszTokens[3];
     919                 : 
     920              16 :     CSLDestroy( papszTokens );
     921              16 :     return TRUE;
     922                 : }
     923                 : 
     924                 : /************************************************************************/
     925                 : /*                       getEPSGObjectCodeValue()                       */
     926                 : /*                                                                      */
     927                 : /*      Fetch a code value from the indicated node.  Should work on     */
     928                 : /*      something of the form <elem xlink:href="urn:...:n" /> or        */
     929                 : /*      something of the form <elem xlink:href="urn:...:">n</a>.        */
     930                 : /************************************************************************/
     931                 : 
     932              16 : static int getEPSGObjectCodeValue( CPLXMLNode *psNode, 
     933                 :                                    const char *pszEPSGObjectType, /*"method" */
     934                 :                                    int nDefault )
     935                 : 
     936                 : {
     937              16 :     if( psNode == NULL )
     938               0 :         return nDefault;
     939                 :     
     940              16 :     CPLString osObjectType, osAuthority, osValue;
     941                 :     const char* pszHrefVal;
     942                 :     
     943              16 :     pszHrefVal = CPLGetXMLValue( psNode, "xlink:href", NULL );
     944              16 :     if (pszHrefVal == NULL)
     945               0 :         pszHrefVal = CPLGetXMLValue( psNode, "href", NULL );
     946                 :     
     947              16 :     if( !ParseOGCDefURN( pszHrefVal,
     948                 :                          &osObjectType, &osAuthority, NULL, &osValue ) )
     949               0 :         return nDefault;
     950                 : 
     951              16 :     if( !EQUAL(osAuthority,"EPSG") 
     952                 :         || !EQUAL(osObjectType, pszEPSGObjectType) )
     953               0 :         return nDefault;
     954                 : 
     955              16 :     if( strlen(osValue) > 0 )
     956              16 :         return atoi(osValue);
     957                 : 
     958               0 :     const char *pszValue = CPLGetXMLValue( psNode, "", NULL);
     959               0 :     if( pszValue != NULL )
     960               0 :         return atoi(pszValue);
     961                 :     else
     962               0 :         return nDefault;
     963                 : }
     964                 : 
     965                 : /************************************************************************/
     966                 : /*                         getProjectionParm()                          */
     967                 : /************************************************************************/
     968                 : 
     969               5 : static double getProjectionParm( CPLXMLNode *psRootNode, 
     970                 :                                  int nParameterCode, 
     971                 :                                  const char * /*pszMeasureType */, 
     972                 :                                  double dfDefault )
     973                 : 
     974                 : {
     975                 :     CPLXMLNode *psUsesParameter;
     976                 : 
     977              25 :     for( psUsesParameter = psRootNode->psChild; 
     978                 :          psUsesParameter != NULL;
     979                 :          psUsesParameter = psUsesParameter->psNext )
     980                 :     {
     981              25 :         if( psUsesParameter->eType != CXT_Element )
     982               5 :             continue;
     983                 : 
     984              20 :         if( !EQUAL(psUsesParameter->pszValue,"usesParameterValue") 
     985                 :             && !EQUAL(psUsesParameter->pszValue,"usesValue") )
     986               5 :             continue;
     987                 : 
     988              15 :         if( getEPSGObjectCodeValue( CPLGetXMLNode(psUsesParameter,
     989                 :                                                   "valueOfParameter"),
     990                 :                                     "parameter", 0 ) == nParameterCode )
     991                 :         {
     992                 :             const char *pszValue = CPLGetXMLValue( psUsesParameter, "value", 
     993               5 :                                                    NULL );
     994                 : 
     995               5 :             if( pszValue != NULL )
     996               5 :                 return atof(pszValue);
     997                 :             else
     998               0 :                 return dfDefault;
     999                 :         }
    1000                 :     }
    1001                 : 
    1002               0 :     return dfDefault;
    1003                 : }
    1004                 : 
    1005                 : /************************************************************************/
    1006                 : /*                         getNormalizedValue()                         */
    1007                 : /*                                                                      */
    1008                 : /*      Parse a node to get it's numerical value, and then normalize    */
    1009                 : /*      into meters of degrees depending on the measure type.           */
    1010                 : /************************************************************************/
    1011                 : 
    1012               3 : static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
    1013                 :                                   const char * /*pszMeasure*/, 
    1014                 :                                   double dfDefault )
    1015                 : 
    1016                 : {
    1017                 :     CPLXMLNode *psTargetNode;
    1018                 :     CPLXMLNode *psValueNode;
    1019                 : 
    1020               3 :     if( pszPath == NULL || strlen(pszPath) == 0 )
    1021               0 :         psTargetNode = psNode;
    1022                 :     else
    1023               3 :         psTargetNode = CPLGetXMLNode( psNode, pszPath );
    1024                 :     
    1025               3 :     if( psTargetNode == NULL )
    1026               0 :         return dfDefault;
    1027                 : 
    1028               3 :     for( psValueNode = psTargetNode->psChild; 
    1029                 :          psValueNode != NULL && psValueNode->eType != CXT_Text;
    1030                 :          psValueNode = psValueNode->psNext ) {}
    1031                 : 
    1032               3 :     if( psValueNode == NULL )
    1033               0 :         return dfDefault;
    1034                 :     
    1035                 :     // Add normalization later.
    1036                 : 
    1037               3 :     return atof(psValueNode->pszValue);
    1038                 : }
    1039                 : 
    1040                 : /************************************************************************/
    1041                 : /*                        importGeogCSFromXML()                         */
    1042                 : /************************************************************************/
    1043                 : 
    1044               1 : static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS, 
    1045                 :                                    CPLXMLNode *psCRS )
    1046                 : 
    1047                 : {
    1048                 :     const char     *pszGeogName, *pszDatumName, *pszEllipsoidName, *pszPMName;
    1049               1 :     double         dfSemiMajor, dfInvFlattening, dfPMOffset = 0.0;
    1050                 : 
    1051                 : /* -------------------------------------------------------------------- */
    1052                 : /*      Set the GEOGCS name from the srsName.                           */
    1053                 : /* -------------------------------------------------------------------- */
    1054                 :     pszGeogName = 
    1055               1 :         CPLGetXMLValue( psCRS, "srsName", "Unnamed GeogCS" );
    1056                 : 
    1057                 : /* -------------------------------------------------------------------- */
    1058                 : /*      If we don't seem to have a detailed coordinate system           */
    1059                 : /*      definition, check if we can define based on an EPSG code.       */
    1060                 : /* -------------------------------------------------------------------- */
    1061                 :     CPLXMLNode     *psDatum;
    1062                 : 
    1063               1 :     psDatum = CPLGetXMLNode( psCRS, "usesGeodeticDatum.GeodeticDatum" );
    1064                 : 
    1065               1 :     if( psDatum == NULL )
    1066                 :     {
    1067               0 :         OGRSpatialReference oIdSRS;
    1068                 : 
    1069               0 :         oIdSRS.SetLocalCS( "dummy" );
    1070               0 :         importXMLAuthority( psCRS, &oIdSRS, "srsID", "LOCAL_CS" );
    1071                 : 
    1072               0 :         if( oIdSRS.GetAuthorityCode( "LOCAL_CS" ) != NULL
    1073                 :             && oIdSRS.GetAuthorityName( "LOCAL_CS" ) != NULL
    1074                 :             && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"),"EPSG") )
    1075                 :         {
    1076                 :             return poSRS->importFromEPSG( 
    1077               0 :                 atoi(oIdSRS.GetAuthorityCode("LOCAL_CS")) );
    1078               0 :         }
    1079                 :     }
    1080                 : 
    1081                 : /* -------------------------------------------------------------------- */
    1082                 : /*      Get datum name.                                                 */
    1083                 : /* -------------------------------------------------------------------- */
    1084                 :     pszDatumName = 
    1085               1 :         CPLGetXMLValue( psDatum, "datumName", "Unnamed Datum" );
    1086                 : 
    1087                 : /* -------------------------------------------------------------------- */
    1088                 : /*      Get ellipsoid information.                                      */
    1089                 : /* -------------------------------------------------------------------- */
    1090                 :     CPLXMLNode *psE;
    1091                 : 
    1092               1 :     psE = CPLGetXMLNode( psDatum, "usesEllipsoid.Ellipsoid" );
    1093                 :     pszEllipsoidName = 
    1094               1 :         CPLGetXMLValue( psE, "ellipsoidName", "Unnamed Ellipsoid" );
    1095                 : 
    1096                 :     dfSemiMajor = getNormalizedValue( psE, "semiMajorAxis", "Linear", 
    1097               1 :                                       SRS_WGS84_SEMIMAJOR );
    1098                 : 
    1099                 :     dfInvFlattening = 
    1100                 :         getNormalizedValue( psE, "secondDefiningParameter.inverseFlattening", 
    1101               1 :                             "Unitless", 0.0 );
    1102                 : 
    1103               1 :     if( dfInvFlattening == 0.0 )
    1104                 :     {
    1105                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1106               0 :                   "Ellipsoid inverseFlattening corrupt or missing." );
    1107               0 :         return OGRERR_CORRUPT_DATA;
    1108                 :     }
    1109                 : 
    1110                 : /* -------------------------------------------------------------------- */
    1111                 : /*      Get the prime meridian.                                         */
    1112                 : /* -------------------------------------------------------------------- */
    1113                 :     CPLXMLNode *psPM;
    1114                 : 
    1115               1 :     psPM = CPLGetXMLNode( psDatum, "usesPrimeMeridian.PrimeMeridian" );
    1116               1 :     if( psPM == NULL )
    1117                 :     {
    1118               0 :         pszPMName = "Greenwich";
    1119               0 :         dfPMOffset = 0.0;
    1120                 :     }
    1121                 :     else
    1122                 :     {
    1123                 :         pszPMName = CPLGetXMLValue( psPM, "meridianName", 
    1124               1 :                                     "Unnamed Prime Meridian");
    1125                 :         dfPMOffset = 
    1126                 :             getNormalizedValue( psPM, "greenwichLongitude.angle",
    1127               1 :                                 "Angular", 0.0 );
    1128                 :     }
    1129                 : 
    1130                 : /* -------------------------------------------------------------------- */
    1131                 : /*      Set the geographic definition.                                  */
    1132                 : /* -------------------------------------------------------------------- */
    1133                 :     poSRS->SetGeogCS( pszGeogName, pszDatumName, 
    1134                 :                       pszEllipsoidName, dfSemiMajor, dfInvFlattening, 
    1135               1 :                       pszPMName, dfPMOffset );
    1136                 : 
    1137                 : /* -------------------------------------------------------------------- */
    1138                 : /*      Look for angular units.  We don't check that all axes match     */
    1139                 : /*      at this time.                                                   */
    1140                 : /* -------------------------------------------------------------------- */
    1141                 : #ifdef notdef
    1142                 :     CPLXMLNode *psAxis;
    1143                 : 
    1144                 :     psAxis = CPLGetXMLNode( psGeo2DCRS, 
    1145                 :                             "EllipsoidalCoordinateSystem.CoordinateAxis" );
    1146                 :     importXMLUnits( psAxis, "AngularUnit", poSRS, "GEOGCS" );
    1147                 : #endif
    1148                 : 
    1149                 : /* -------------------------------------------------------------------- */
    1150                 : /*      Can we set authorities for any of the levels?                   */
    1151                 : /* -------------------------------------------------------------------- */
    1152               1 :     importXMLAuthority( psCRS, poSRS, "srsID", "GEOGCS" );
    1153               1 :     importXMLAuthority( psDatum, poSRS, "datumID", "GEOGCS|DATUM" );
    1154                 :     importXMLAuthority( psE, poSRS, "ellipsoidID", 
    1155               1 :                         "GEOGCS|DATUM|SPHEROID" );
    1156                 :     importXMLAuthority( psDatum, poSRS, 
    1157                 :                         "usesPrimeMeridian.PrimeMeridian.meridianID",
    1158               1 :                         "GEOGCS|PRIMEM" );
    1159                 : 
    1160               1 :     poSRS->Fixup();
    1161                 :     
    1162               1 :     return OGRERR_NONE;
    1163                 : }
    1164                 : 
    1165                 : /************************************************************************/
    1166                 : /*                        importProjCSFromXML()                         */
    1167                 : /************************************************************************/
    1168                 : 
    1169               1 : static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS, 
    1170                 :                                    CPLXMLNode *psCRS )
    1171                 : 
    1172                 : {
    1173                 :     CPLXMLNode *psSubXML;
    1174                 :     OGRErr eErr;
    1175                 : 
    1176                 : /* -------------------------------------------------------------------- */
    1177                 : /*      Setup the PROJCS node with a name.                              */
    1178                 : /* -------------------------------------------------------------------- */
    1179               1 :     poSRS->SetProjCS( CPLGetXMLValue( psCRS, "srsName", "Unnamed" ) );
    1180                 : 
    1181                 : /* -------------------------------------------------------------------- */
    1182                 : /*      Get authority information if available.  If we got it, and      */
    1183                 : /*      we seem to be lacking inline definition values, try and         */
    1184                 : /*      define according to the EPSG code for the PCS.                  */
    1185                 : /* -------------------------------------------------------------------- */
    1186               1 :     importXMLAuthority( psCRS, poSRS, "srsID", "PROJCS" );
    1187                 : 
    1188               1 :     if( poSRS->GetAuthorityCode( "PROJCS" ) != NULL
    1189                 :         && poSRS->GetAuthorityName( "PROJCS" ) != NULL
    1190                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG")
    1191                 :         && (CPLGetXMLNode( psCRS, "definedByConversion.Conversion" ) == NULL
    1192                 :             || CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" ) == NULL) )
    1193                 :     {
    1194               0 :         return poSRS->importFromEPSG( atoi(poSRS->GetAuthorityCode("PROJCS")) );
    1195                 :     }
    1196                 : 
    1197                 : /* -------------------------------------------------------------------- */
    1198                 : /*      Try to set the GEOGCS info.                                     */
    1199                 : /* -------------------------------------------------------------------- */
    1200                 :     
    1201               1 :     psSubXML = CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" );
    1202               1 :     if( psSubXML != NULL )
    1203                 :     {
    1204               1 :         eErr = importGeogCSFromXML( poSRS, psSubXML );
    1205               1 :         if( eErr != OGRERR_NONE )
    1206               0 :             return eErr;
    1207                 :     }
    1208                 : 
    1209                 : /* -------------------------------------------------------------------- */
    1210                 : /*      Get the conversion node.  It should be the only child of the    */
    1211                 : /*      definedByConversion node.                                       */
    1212                 : /* -------------------------------------------------------------------- */
    1213               1 :     CPLXMLNode *psConv = NULL;
    1214                 : 
    1215               1 :     psConv = CPLGetXMLNode( psCRS, "definedByConversion.Conversion" );
    1216               1 :     if( psConv == NULL || psConv->eType != CXT_Element )
    1217                 :     {
    1218                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1219                 :                   "Unable to find a conversion node under the definedByConversion\n"
    1220               0 :                   "node of the ProjectedCRS." );
    1221               0 :         return OGRERR_CORRUPT_DATA;
    1222                 :     }
    1223                 : 
    1224                 : /* -------------------------------------------------------------------- */
    1225                 : /*      Determine the conversion method in effect.                      */
    1226                 : /* -------------------------------------------------------------------- */
    1227                 :     int nMethod = getEPSGObjectCodeValue( CPLGetXMLNode( psConv, "usesMethod"),
    1228               1 :                                           "method", 0 );
    1229                 :     
    1230                 : /* -------------------------------------------------------------------- */
    1231                 : /*      Transverse Mercator.                                            */
    1232                 : /* -------------------------------------------------------------------- */
    1233               1 :     if( nMethod == 9807 ) 
    1234                 :     {
    1235                 :         poSRS->SetTM( 
    1236                 :             getProjectionParm( psConv, 8801, "Angular", 0.0 ), 
    1237                 :             getProjectionParm( psConv, 8802, "Angular", 0.0 ), 
    1238                 :             getProjectionParm( psConv, 8805, "Unitless", 1.0 ), 
    1239                 :             getProjectionParm( psConv, 8806, "Linear", 0.0 ),
    1240               1 :             getProjectionParm( psConv, 8807, "Linear", 0.0 ) );
    1241                 :     }
    1242                 : 
    1243                 : /* -------------------------------------------------------------------- */
    1244                 : /*      Didn't recognise?                                               */
    1245                 : /* -------------------------------------------------------------------- */
    1246                 :     else
    1247                 :     {
    1248                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1249                 :                   "Conversion method %d not recognised.", 
    1250               0 :                   nMethod );
    1251               0 :         return OGRERR_CORRUPT_DATA;
    1252                 :     }
    1253                 : 
    1254                 : 
    1255                 : /* -------------------------------------------------------------------- */
    1256                 : /*      Cleanup and return.                                             */
    1257                 : /* -------------------------------------------------------------------- */
    1258               1 :     poSRS->Fixup();
    1259                 : 
    1260                 :     // Need to get linear units here!
    1261                 : 
    1262               1 :     return OGRERR_NONE;
    1263                 : }
    1264                 : 
    1265                 : /************************************************************************/
    1266                 : /*                           importFromXML()                            */
    1267                 : /************************************************************************/
    1268                 : 
    1269                 : /** 
    1270                 :  * \brief Import coordinate system from XML format (GML only currently).
    1271                 :  *
    1272                 :  * This method is the same as the C function OSRImportFromXML()
    1273                 :  * @param pszXML XML string to import
    1274                 :  * @return OGRERR_NONE on success or OGRERR_CORRUPT_DATA on failure.
    1275                 :  */
    1276               1 : OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
    1277                 : 
    1278                 : {
    1279                 :     CPLXMLNode *psTree;
    1280               1 :     OGRErr  eErr = OGRERR_UNSUPPORTED_SRS;
    1281                 : 
    1282               1 :     this->Clear();
    1283                 :         
    1284                 : /* -------------------------------------------------------------------- */
    1285                 : /*      Parse the XML.                                                  */
    1286                 : /* -------------------------------------------------------------------- */
    1287               1 :     psTree = CPLParseXMLString( pszXML );
    1288                 :     
    1289               1 :     if( psTree == NULL )
    1290               0 :         return OGRERR_CORRUPT_DATA;
    1291                 : 
    1292               1 :     CPLStripXMLNamespace( psTree, "gml", TRUE );
    1293                 : 
    1294                 : /* -------------------------------------------------------------------- */
    1295                 : /*      Import according to the root node type.  We walk through        */
    1296                 : /*      root elements as there is sometimes prefix stuff like           */
    1297                 : /*      <?xml>.                                                         */
    1298                 : /* -------------------------------------------------------------------- */
    1299               1 :     CPLXMLNode *psNode = psTree;
    1300                 : 
    1301               1 :     for( psNode = psTree; psNode != NULL; psNode = psNode->psNext )
    1302                 :     {
    1303               1 :         if( EQUAL(psNode->pszValue,"GeographicCRS") )
    1304                 :         {
    1305               0 :             eErr = importGeogCSFromXML( this, psNode );
    1306               0 :             break;
    1307                 :         }
    1308                 :         
    1309               1 :         else if( EQUAL(psNode->pszValue,"ProjectedCRS") )
    1310                 :         {
    1311               1 :             eErr = importProjCSFromXML( this, psNode );
    1312               1 :             break;
    1313                 :         }
    1314                 :     }
    1315                 : 
    1316               1 :     CPLDestroyXMLNode( psTree );
    1317                 : 
    1318               1 :     return eErr;
    1319                 : }
    1320                 : 
    1321                 : /************************************************************************/
    1322                 : /*                          OSRImportFromXML()                          */
    1323                 : /************************************************************************/
    1324                 : 
    1325                 : /** 
    1326                 :  * \brief Import coordinate system from XML format (GML only currently).
    1327                 :  *
    1328                 :  * This function is the same as OGRSpatialReference::importFromXML().
    1329                 :  */
    1330               1 : OGRErr OSRImportFromXML( OGRSpatialReferenceH hSRS, const char *pszXML )
    1331                 : 
    1332                 : {
    1333               1 :     VALIDATE_POINTER1( hSRS, "OSRImportFromXML", CE_Failure );
    1334                 : 
    1335               1 :     return ((OGRSpatialReference *) hSRS)->importFromXML( pszXML );
    1336                 : }

Generated by: LCOV version 1.7