[mapserver-commits] r9952 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Wed Mar 17 17:13:57 EDT 2010


Author: assefa
Date: 2010-03-17 17:13:55 -0400 (Wed, 17 Mar 2010)
New Revision: 9952

Modified:
   trunk/mapserver/HISTORY.TXT
   trunk/mapserver/mapgml.c
   trunk/mapserver/mapwfs.c
   trunk/mapserver/mapwfs11.c
Log:
Add support for mulitiple srs in WFS (#3227)

Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT	2010-03-17 18:51:18 UTC (rev 9951)
+++ trunk/mapserver/HISTORY.TXT	2010-03-17 21:13:55 UTC (rev 9952)
@@ -14,6 +14,8 @@
 Current Version (SVN trunk):
 ----------------------------
 
+- Add support for multiliple srs in  WFS 1.1.0 (#3227)
+
 - Fixed PHP/MapScript owsRequestObj->loadParams() method when using php in a non cgi/fcgi/cli mode. (#1975)
 
 - Ensure that non-file raster datasets work (#3253) 

Modified: trunk/mapserver/mapgml.c
===================================================================
--- trunk/mapserver/mapgml.c	2010-03-17 18:51:18 UTC (rev 9951)
+++ trunk/mapserver/mapgml.c	2010-03-17 21:13:55 UTC (rev 9952)
@@ -1414,7 +1414,8 @@
 **
 ** Similar to msGMLWriteQuery() but tuned for use with WFS 1.0.0
 */
-int msGMLWriteWFSQuery(mapObj *map, FILE *stream, int startindex, int maxfeatures, char *default_namespace_prefix, int outputformat)
+int msGMLWriteWFSQuery(mapObj *map, FILE *stream, int startindex, int maxfeatures, 
+                       char *default_namespace_prefix, int outputformat)
 {
 #ifdef USE_WFS_SVR
   int status;
@@ -1436,6 +1437,7 @@
   const char *axis = NULL;
   int bSwapAxis = 0;
   double tmp;
+  const char *srsMap =  NULL;
 
   msInitShape(&shape);
 
@@ -1467,7 +1469,11 @@
           resultBounds.maxy = tmp;
 
       }
-      gmlWriteBounds(stream, outputformat, &resultBounds, msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE), "      ");
+      srsMap = msOWSGetEPSGProj(&(map->projection), NULL, "FGO", MS_TRUE);
+      if (!srsMap)
+        msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE);
+
+      gmlWriteBounds(stream, outputformat, &resultBounds, srsMap, "      ");
   }
   /* step through the layers looking for query results */
   for(i=0; i<map->numlayers; i++) {
@@ -1552,9 +1558,12 @@
         /* write the feature geometry and bounding box */
         if(!(geometryList && geometryList->numgeometries == 1 && strcasecmp(geometryList->geometries[0].name, "none") == 0)) {
 #ifdef USE_PROJ
-          if(msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE)) { /* use the map projection first*/
-            gmlWriteBounds(stream, outputformat, &(shape.bounds), msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE), "        ");
-            gmlWriteGeometry(stream, geometryList, outputformat, &(shape), msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE), namespace_prefix, "        "); 
+          srsMap = msOWSGetEPSGProj(&(map->projection), NULL, "FGO", MS_TRUE);
+          if (!srsMap)
+            msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE);
+          if(srsMap) { /* use the map projection first*/
+            gmlWriteBounds(stream, outputformat, &(shape.bounds), srsMap, "        ");
+            gmlWriteGeometry(stream, geometryList, outputformat, &(shape), srsMap, namespace_prefix, "        "); 
           } else { /* then use the layer projection and/or metadata */
             gmlWriteBounds(stream, outputformat, &(shape.bounds), msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FGO", MS_TRUE), "        ");
             gmlWriteGeometry(stream, geometryList, outputformat, &(shape), msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FGO", MS_TRUE), namespace_prefix, "        ");

Modified: trunk/mapserver/mapwfs.c
===================================================================
--- trunk/mapserver/mapwfs.c	2010-03-17 18:51:18 UTC (rev 9951)
+++ trunk/mapserver/mapwfs.c	2010-03-17 21:13:55 UTC (rev 9952)
@@ -131,6 +131,209 @@
   msIO_printf("    </%s>\n", request);
 }
 
+
+/* msWFSLocateSRSInList()
+**
+** Utility function to check if a space separated list contains of srs
+** contain the one passed in argument.  The list comes normaly
+** from ows_srs metadata, and is expected to using the simple EPSG notation
+** (EPSG:4326 ESPG:42304 ...). The srs comes from the query strin and can either
+** be of simple EPSG format or using gc:def:crs:EPSG:xxx format
+*/
+int msWFSLocateSRSInList(const char *pszList, const char *srs)
+{
+    int nTokens,i;
+    char **tokens = NULL;
+    int bFound = MS_FALSE;
+    char epsg_string[100];
+    const char *code;
+
+    if (!pszList || !srs)
+      return MS_FALSE;
+
+    if (strncasecmp(srs, "EPSG:",5) == 0)
+      code = srs+5;
+    else if (strncasecmp(srs, "urn:ogc:def:crs:EPSG:",21) == 0)
+      code = srs+21;
+    else if (strncasecmp(srs, "urn:EPSG:geographicCRS:",23) == 0)
+      code = srs + 23;
+    else
+      return MS_FALSE;
+    
+    sprintf( epsg_string, "EPSG:%s", code );
+
+    tokens = msStringSplit(pszList, ' ', &nTokens );
+    if (tokens && nTokens > 0)
+    {
+        for (i=0; i<nTokens; i++)
+        {
+            if (strcasecmp(tokens[i],  epsg_string) == 0)
+            {
+                bFound = MS_TRUE;
+                break;
+            }
+        }
+        msFreeCharArray(tokens, nTokens);
+    }
+    
+    return bFound;
+}
+
+/* msWFSGetFeatureApplySRS()
+**
+** Utility function called from msWFSGetFeature. It is assumed that at this point
+** all queried layers are turned ON
+*/
+static int msWFSGetFeatureApplySRS(mapObj *map, const char *srs, const char *version)
+{
+    int nVersion = OWS_1_1_0;
+    const char *pszLayerSRS=NULL;
+    const char *pszMapSRS=NULL;
+    char *pszOutputSRS=NULL;
+    layerObj *lp;
+    int i;
+    
+    if (version && strncmp(version,"1.0",3)==0)
+      nVersion = OWS_1_0_0;
+
+    /*validation of SRS
+      - wfs 1.0 does not have an srsname parameter so all queried layers should be advertized using the
+        same srs. For wfs 1.1.0 an srsName can be passed, we should validate that It is valid for all 
+        queries layers
+    */
+    pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_TRUE);
+    if (srs == NULL || nVersion == OWS_1_0_0)
+    {
+        for (i=0; i<map->numlayers; i++)
+        {
+            lp = lp = GET_LAYER(map, i);
+            if (lp->status != MS_ON)
+              continue;
+
+            if (pszMapSRS)
+              pszLayerSRS = pszMapSRS;
+            else
+              pszLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE);
+              
+            if (pszLayerSRS == NULL) 
+            {
+                msSetError(MS_WFSERR, 
+                           "Server config error: SRS must be set at least at the map or at the layer level.",
+                           "msWFSGetFeature()");
+                if (pszOutputSRS)
+                  msFree(pszOutputSRS);
+                return MS_FAILURE;
+            }
+            if (pszOutputSRS == NULL)
+              pszOutputSRS = strdup(pszLayerSRS);
+            else if (strcasecmp(pszLayerSRS,pszOutputSRS) != 0) 
+            {
+                msSetError(MS_WFSERR, 
+                           "Invalid GetFeature Request: All TYPENAMES in a single GetFeature request must have been advertized in the same SRS.  Please check the capabilities and reformulate your request.",
+                           "msWFSGetFeature()");
+                if (pszOutputSRS)
+                  msFree(pszOutputSRS);
+                return MS_FAILURE;
+            }
+            
+        }
+    }
+    else /*srs is given so it should be valid for all layers*/
+    {
+        /*get all the srs defined at the map level and check them aginst the srsName passed
+          as argument*/
+        pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_FALSE);
+        if (pszMapSRS)
+        {
+            if (!msWFSLocateSRSInList(pszMapSRS, srs))
+            {
+                msSetError(MS_WFSERR, 
+                           "Invalid GetFeature Request:Invalid SRS.  Please check the capabilities and reformulate your request.",
+                           "msWFSGetFeature()");
+                return MS_FAILURE;
+            }
+            pszOutputSRS = strdup(srs);
+        }
+        else
+        {
+            for (i=0; i<map->numlayers; i++)
+            {
+                lp = lp = GET_LAYER(map, i);
+                if (lp->status != MS_ON)
+                  continue;
+                
+                pszLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_FALSE);
+                if (!pszLayerSRS)
+                {
+                    msSetError(MS_WFSERR, 
+		       "Server config error: SRS must be set at least at the map or at the layer level.",
+		       "msWFSGetFeature()");
+                    return MS_FAILURE;
+                }
+                if (!msWFSLocateSRSInList(pszLayerSRS, srs))
+                {
+                    msSetError(MS_WFSERR, 
+                               "Invalid GetFeature Request:Invalid SRS.  Please check the capabilities and reformulate your request.",
+                               "msWFSGetFeature()");
+                    return MS_FAILURE;
+                }
+            }
+            pszOutputSRS = strdup(srs);
+        }
+    }
+
+    if (pszOutputSRS && nVersion >= OWS_1_1_0)
+    {     
+          /*check if the srs passed is valid. Assuming that it is an EPSG:xxx format,
+            Or urn:ogc:def:crs:EPSG:xxx format. */
+        if (strncasecmp(pszOutputSRS, "EPSG:", 5) == 0 ||
+            strncasecmp(pszOutputSRS, "urn:ogc:def:crs:EPSG:",21) == 0)
+        {
+            /*we load the projection sting in the map and possibly 
+              set the axis order*/
+            msFreeProjection(&map->projection);
+            msLoadProjectionStringEPSG(&(map->projection), pszOutputSRS);
+        }
+        else if (strncasecmp(pszOutputSRS, "urn:EPSG:geographicCRS:",23) == 0)
+        {
+            char epsg_string[100];
+            const char *code;
+
+            code = pszOutputSRS + 23;
+            
+            sprintf( epsg_string, "EPSG:%s", code );
+            
+            /*we load the projection sting in the map and possibly 
+              set the axis order*/
+            msFreeProjection(&map->projection);
+            msLoadProjectionStringEPSG(&(map->projection), epsg_string);
+        }
+    }
+    /* Set map output projection to which output features should be reprojected */
+    else if (pszOutputSRS && strncasecmp(pszOutputSRS, "EPSG:", 5) == 0) 
+    {
+        int nTmp =0;
+        msFreeProjection(&map->projection);
+        msInitProjection(&map->projection);
+
+        if (nVersion >= OWS_1_1_0)
+          nTmp = msLoadProjectionStringEPSG(&(map->projection), pszOutputSRS);
+        else
+          nTmp = msLoadProjectionString(&(map->projection), pszOutputSRS);
+
+        if (nTmp != 0) {
+            msSetError(MS_WFSERR, "msLoadProjectionString() failed", "msWFSGetFeature()");
+            return MS_FAILURE;
+        }
+    }
+    
+
+    if (pszOutputSRS)
+      msFree(pszOutputSRS);
+    return MS_SUCCESS;
+}
+
+
 /* msWFSIsLayerSupported()
 **
 ** Returns true (1) is this layer meets the requirements to be served as
@@ -256,7 +459,7 @@
    else
    {
        /* Map has no SRS.  Use layer SRS or produce a warning. */
-       pszWfsSrs = msOWSGetEPSGProj(&(map->projection),&(map->web.metadata), "FO", MS_TRUE);
+       pszWfsSrs = msOWSGetEPSGProj(&(lp->projection),&(lp->metadata), "FO", MS_TRUE);
    }
 
    msOWSPrintEncodeParam(stdout, "(at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs_srs metadata", 
@@ -1014,7 +1217,6 @@
   const char *typename="";
   char       *script_url=NULL, *script_url_encoded;
   rectObj     bbox;
-  const char  *pszOutputSRS = NULL;
   
   char **layers = NULL;
   int numlayers = 0;
@@ -1046,7 +1248,6 @@
   gmlNamespaceListObj *namespaceList=NULL; /* for external application schema support */
   char **papszPropertyName = NULL;
   int nPropertyNames = 0;
-  const char *pszMapSRS = NULL;
   int nQueriedLayers=0;
   layerObj *lpQueried=NULL;
 
@@ -1122,7 +1323,6 @@
       msFreeCharArray(tokens, n);
 
    
-    pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_TRUE);
 
     /* Keep only selected layers, set to OFF by default. */
     for(j=0; j<map->numlayers; j++) {
@@ -1144,7 +1344,6 @@
 	lp = GET_LAYER(map, j);
 	
 	if (msWFSIsLayerSupported(lp) && lp->name && strcasecmp(lp->name, layers[k]) == 0) {
-	  const char *pszThisLayerSRS;
 	  bLayerFound = MS_TRUE;
 	  
 	  lp->status = MS_ON;
@@ -1291,34 +1490,6 @@
 
               }
           }
-              
-
-          
-	  /* See comments in msWFSGetCapabilities() about the rules for SRS. */
-	  if ((pszThisLayerSRS = pszMapSRS) == NULL) {
-	    pszThisLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE);
-	  }
-	  
-	  if (pszThisLayerSRS == NULL) {
-	    msSetError(MS_WFSERR, 
-		       "Server config error: SRS must be set at least at the map or at the layer level.",
-		       "msWFSGetFeature()");
-	    return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion);
-	  }
-
-	  /* Keep track of output SRS.  If different from value */
-	  /* from previous layers then this is an invalid request */
-	  /* i.e. all layers in a single request must be in the */
-	  /* same SRS. */
-	  if (pszOutputSRS == NULL) {
-	    pszOutputSRS = pszThisLayerSRS;
-	  } else if (strcasecmp(pszThisLayerSRS,pszOutputSRS) != 0) {
-	    msSetError(MS_WFSERR, 
-		       "Invalid GetFeature Request: All TYPENAMES in a single GetFeature request must have been advertized in the same SRS.  Please check the capabilities and reformulate your request.",
-		       "msWFSGetFeature()");
-	    return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion);
-	  }         
-
         }
       }
 
@@ -1333,6 +1504,8 @@
       }
     }
   }
+
+
   if (papszPropertyName && nPropertyNames > 0)
   {
     for (i=0; i<nPropertyNames; i++)
@@ -1600,6 +1773,7 @@
 	free(paszFilter);
     }/* end if filter set */
 
+
     if (bFeatureIdSet)
     {
         char **tokens = NULL, **tokens1=NULL ;
@@ -1724,74 +1898,14 @@
     }
 #endif
 
+    
     if(layers)
       msFreeCharArray(layers, numlayers);
 
+    if (msWFSGetFeatureApplySRS(map, paramsObj->pszSrs, paramsObj->pszVersion) == MS_FAILURE)
+      return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion);
 
     /*
-      srs is defined for wfs 1.1. If it is available. If it used to set 
-      the map projection. For EPSG codes between 4000 and 5000 
-      that coordinates order follow what is defined  in the ESPG database
-      see #2899
-  */
-    if (strncmp(paramsObj->pszVersion,"1.1",3) == 0 && paramsObj->pszSrs && pszOutputSRS)
-    {     
-          /*check if the srs passed is valid. Assuming that it is an EPSG:xxx format,
-            Or urn:ogc:def:crs:EPSG:xxx format. */
-        if (strncasecmp(paramsObj->pszSrs, "EPSG:", 5) == 0)
-        {
-            if (strcasecmp(paramsObj->pszSrs, pszOutputSRS) != 0)
-            {
-                msSetError(MS_WFSERR, 
-                           "Invalid GetFeature Request: SRSNAME value should be valid for all the TYPENAMES. Please check the capabilities and reformulate your request.",
-                           "msWFSGetFeature()");
-                return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion);
-            }
-                /*we load the projection sting in the map and possibly 
-                  set the axis order*/
-            msFreeProjection(&map->projection);
-            msLoadProjectionStringEPSG(&(map->projection), paramsObj->pszSrs);
-        }
-        else if (strncasecmp(paramsObj->pszSrs, "urn:EPSG:geographicCRS:",23) == 0)
-        {
-            char epsg_string[100];
-            const char *code;
-
-            code = paramsObj->pszSrs + 23;
-            
-            sprintf( epsg_string, "EPSG:%s", code );
-            if (strcasecmp(epsg_string, pszOutputSRS) != 0)
-            {
-                msSetError(MS_WFSERR, 
-                           "Invalid GetFeature Request: SRSNAME value should be valid for all the TYPENAMES. Please check the capabilities and reformulate your request.",
-                           "msWFSGetFeature()");
-                return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion);
-            }
-                /*we load the projection sting in the map and possibly 
-                  set the axis order*/
-            msFreeProjection(&map->projection);
-            msLoadProjectionStringEPSG(&(map->projection), epsg_string);
-        }
-    }
-    /* Set map output projection to which output features should be reprojected */
-    else if (pszOutputSRS && strncasecmp(pszOutputSRS, "EPSG:", 5) == 0) 
-    {
-        int nTmp =0;
-        msFreeProjection(&map->projection);
-        msInitProjection(&map->projection);
-
-        if (strncmp(paramsObj->pszVersion,"1.1",3) == 0)
-          nTmp = msLoadProjectionStringEPSG(&(map->projection), pszOutputSRS);
-        else
-          nTmp = msLoadProjectionString(&(map->projection), pszOutputSRS);
-
-        if (nTmp != 0) {
-            msSetError(MS_WFSERR, "msLoadProjectionString() failed", "msWFSGetFeature()");
-            return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion);
-        }
-    }
-
-    /*
     ** Perform Query (only BBOX for now)
     */
     /* __TODO__ Using a rectangle query may not be the most efficient way */
@@ -1800,9 +1914,15 @@
 
       if (!bBBOXSet)
       {
+          const char *pszMapSRS=NULL, *pszLayerSRS=NULL;
           bbox = map->extent;
           map->query.type = MS_QUERY_BY_RECT; /* setup the query */
           map->query.mode = MS_QUERY_MULTIPLE;
+
+          /*if srsName was given for wfs 1.1.0, It is at this point loaded into the 
+            map object and should be used*/
+          if(!paramsObj->pszSrs)
+            pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_TRUE);
           for(j=0; j<map->numlayers; j++) 
           {
               layerObj *lp;
@@ -1818,11 +1938,29 @@
                            sprintf(szBuf, "init=epsg:%.10s", pszMapSRS+5);
                 
                            if (msLoadProjectionString(&(map->projection), szBuf) != 0) {
-                               msSetError(MS_WFSERR, "msLoadProjectionString() failed: %s", "msWFSGetFeature()", szBuf);
-                               return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion);
+                               msSetError(MS_WFSERR, "msLoadProjectionString() failed: %s", 
+                                          "msWFSGetFeature()", szBuf);        
+                               return msWFSException(map, "mapserv", "NoApplicableCode", 
+                                                     paramsObj->pszVersion);
                            }
+                           
                        }
 
+                       /*make sure that the layer projectsion is loaded. 
+                         It could come from a ows/wfs_srs metadata*/
+                       if (lp->projection.numargs == 0)
+                       {
+                           pszLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE);
+                           if (pszLayerSRS)
+                           {
+                               if (strncmp(pszLayerSRS, "EPSG:", 5) == 0) 
+                               {
+                                   sprintf(szBuf, "init=epsg:%.10s", pszLayerSRS+5);
+                                   msLoadProjectionString(&(lp->projection), szBuf);
+                               }
+                           }
+                       }
+
                        if (msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) {
                            msProjectRect(&lp->projection, &map->projection, &(ext));
                        }
@@ -2674,7 +2812,7 @@
                 wfsparams->pszRequest = strdup("GetCapabilities");
                 pszValue = (char*)CPLGetXMLValue(psGetCapabilities,  "version", 
                                                  NULL);
-                /* version is optional is the GetCapabilities. If not */
+                /* version is optional for the GetCapabilities. If not */
                 /* provided, set it. */
                 if (pszValue)
                   wfsparams->pszVersion = strdup(pszValue);

Modified: trunk/mapserver/mapwfs11.c
===================================================================
--- trunk/mapserver/mapwfs11.c	2010-03-17 18:51:18 UTC (rev 9951)
+++ trunk/mapserver/mapwfs11.c	2010-03-17 21:13:55 UTC (rev 9952)
@@ -105,7 +105,8 @@
     const char *value    = NULL;
     const char *encoding = NULL;
     char *encoded=NULL;
-      
+    char **tokens;
+    int n=0,i=0;      
 
     encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
     if (!encoding)
@@ -113,7 +114,6 @@
 
     psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType");
 
-
     /*if there is an encoding using it on some of the items*/
     psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", lp->name, encoding);
 
@@ -151,14 +151,24 @@
             NULL, "Keyword", encoded, ',' );
 	msFree(encoded);
     }
-    /*srs only supposrt DefaultSRS with the same logic as for wfs1.0
-      TODO support OtherSRS*/
-    value = msOWSGetEPSGProj(&(map->projection),&(map->web.metadata),"FO",MS_TRUE);
+      /*support DefaultSRS and OtherSRS*/
+    value = msOWSGetProjURN(&(map->projection),&(map->web.metadata),"FO",MS_FALSE);
     if (!value)
-      value =  msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE);
-  
-    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST value);
-    if (!value)
+      value = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE);
+
+    if (value)
+    {
+        tokens = msStringSplit(value, ' ', &n);
+        if (tokens && n > 0)
+        {
+            psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]);
+            for (i=1; i<n; i++)
+              psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);
+
+            msFreeCharArray(tokens, n);
+        }
+    }
+    else
       xmlAddSibling(psNode,
                     xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context."));
 



More information about the mapserver-commits mailing list