Skip To Content

Personnalisation d'une réponse WMS GetFeatureInfo

WMS services prend en charge tout un ensemble d’opérations, comme GetCapabilities, GetMap, GetStyles, etc, qui permettent aux applications client de fonctionner avec le service en ajoutant des paramètres à l’URL de service. L'opération GetFeatureInfo fonctionne de manière similaire et vise à renvoyer les attributs des entités demandées dans une carte dans différents formats tels que HTML, XML et texte brut.

L'exemple suivant présente une demande GetFeatureInfo et la réponse correspondante au format HTML par défaut.

Requête

http://gisserver.domain.com/arcgis/services/ihs_petroleum/MapServer/WMSServer?&service=WMS&version=1.1.0&request=GetFeatureInfo&layers=fields&query_layers=fields&styles=&bbox=47.130647,8.931116,48.604188,29.54223&srs=EPSG:4326&feature_count=10&x=562&y=193&height=445&width=1073&info_format=text/html&

Réponse

Réponse GetFeatureInfo HTML par défaut

Dans bien des cas, la réponse HTML, XML ou texte brut par défaut convient, mais vous pourriez vouloir personnaliser le format ou la structure de la réponse dans certaines situations, afin d’exécuter une logique métier particulière. Par exemple, pour des raisons d'interopérabilité, vous pourriez désirer recevoir les informations sur l'entité dans une structure standard telle que GML ou GeoJSON.

Modèles XSLT

Les modèles de type XSLT permettent de générer un résultat lisible à partir d’une réponse GetFeatureInfo WMS. Par exemple, lorsque vous envoyez une requête GetFeatureInfo WMS au serveur, le serveur répond avec les entités demandées au format XML. Le modèle XSLT "traduit" alors le code XML dans le format spécifié, par exemple HTML ou texte brut, rendant ainsi lisible la réponse finale.

L’examen de la réponse XML GetFeatureInfo WMS et des modèles XSLT par défaut fournis avec l’installation de ArcGIS Server vous permettra de mieux comprendre comment personnaliser une réponse GetFeatureInfo. Les sections suivantes décrivent chacun d'entre eux plus en détail.

Réponse GetFeatureInfo au format XML

Ci-dessous, découvrez un exemple au format XML depuis une réponse GetFeatureInfo dans un service WMS :

<?xml version="1.0" encoding="UTF-8"?>
<esri_wms:FeatureInfoResponse version="1.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:esri_wms="http://www.esri.com/wms" xmlns="http://www.esri.com/wms">
  <esri_wms:FeatureInfoCollection layername="fields">
    <esri_wms:FeatureInfo>
      <esri_wms:Field>
        <esri_wms:FieldName><![CDATA[OBJECTID]]></esri_wms:FieldName>
        <esri_wms:FieldValue><![CDATA[1]]></esri_wms:FieldValue>
      </esri_wms:Field>
      <esri_wms:Field>
        <esri_wms:FieldName><![CDATA[Shape]]></esri_wms:FieldName>
        <esri_wms:FieldValue><![CDATA[Polygon]]></esri_wms:FieldValue>
      </esri_wms:Field>
      <esri_wms:Field>
        <esri_wms:FieldName><![CDATA[Shape_Area]]></esri_wms:FieldName>
        <esri_wms:FieldValue><![CDATA[0.009079]]></esri_wms:FieldValue>
      </esri_wms:Field>
        ...
        <!-- there could be more <esri_wms:Field> -->
        ...
      <esri_wms:Field>
        <esri_wms:FieldGeometry>
          <esri_wms:Point><![CDATA[0,0]]></esri_wms:Point>
          <esri_wms:Multipoint>
            <esri_wms:Point><![CDATA[0,45]]></esri_wms:Point>
            <esri_wms:Point><![CDATA[10,55]]></esri_wms:Point>
            <!-- there could be more <esri_wms:Point> -->
          </esri_wms:Multipoint>
          <esri_wms:Polyline>
            <esri_wms:Path>
              <esri_wms:Point><![CDATA[0,45]]></esri_wms:Point>
              <esri_wms:Point><![CDATA[10,55]]></esri_wms:Point>
              <!-- there could be more <esri_wms:Point> -->
            </esri_wms:Path>
            <!-- there could be more <esri_wms:Path> -->
          </esri_wms:Polyline>
          <esri_wms:Polygon>
            <esri_wms:Ring>
              <esri_wms:Point><![CDATA[0,45]]></esri_wms:Point>
              <esri_wms:Point><![CDATA[10,55]]></esri_wms:Point>
              <esri_wms:Point><![CDATA[15,25]]></esri_wms:Point>
              <!-- there could be more <esri_wms:Point> -->
            </esri_wms:Ring>
            <!-- there could be more <esri_wms:Ring> -->
          </esri_wms:Polygon>
        </esri_wms:FieldGeometry>
      </esri_wms:Field>
    </esri_wms:FeatureInfo>
    ...
    <!-- there could be more <esri_wms:FeatureInfo> -->
    ...
  </esri_wms:FeatureInfoCollection>
  ...
  <!-- there could be more <esri_wms:FeatureInfoCollection> -->
  ...
</esri_wms:FeatureInfoResponse>

Remarquez les détails suivants :

  • La balise racine <FeatureInfoResponse> peut contenir plusieurs éléments <FeatureInfoCollection>.
  • Chaque élément <FeatureInfoCollection> contient les champs et valeurs d'attribut de toutes les entités identifiées dans une couche WMS.
  • Les informations relatives à une seule entité identifiée sont contenues dans une balise <FeatureInfo>. Remarquez la combinaison nom-valeur pour chaque champ.
  • Les informations de référence spatiale sont comprises avec chaque balise <FeatureInfo>.
  • Si disponible, la géométrie d’entité est renvoyée dans la balise <FieldGeometry>.
  • Une géométrie de champ peut contenir une géométrie de type point, multipoints, polyligne ou polygone.

Modèles XSLT par défaut

ArcGIS Server est fourni avec des modèles XSLT pour les formats pris en charge répertoriés dans les fichiers de compétences WMS. Par exemple, si vous ouvrez le répertoire de ces modèles sur <emplacement d’installation de ArcGIS Server>\Styles\WMS, voici ce qui s’affiche :

  • featureinfo_application_geojson.xsl
  • featureinfo_application_vnd.esri.wms_featureinfo_xml.xsl
  • featureinfo_application_vnd.ogc.wms_xml.xsl
  • featureinfo_text_html.xsl
  • featureinfo_text_plain.xsl
  • featureinfo_text_xml.xsl

Comme leur nom l'indique, chaque modèle sert à produire une réponse GetFeatureInfo par défaut dans un format lisible, tel que GeoJSON, texte brut et XML.

La table HTML en exemple avec la légende bleue présentée au début de cette rubrique a été réalisée à l’aide du modèle HTML XSLT par défaut. Sinon, si vous souhaitez obtenir une réponse au format XML brut, vous pouvez définir le paramètre de requête GetFeatureInfo INFO_FORMAT sur application/vnd.esri.wms_raw_xml. Vous pouvez utiliser cette méthode pour créer votre propre modèle XSLT.

Personnalisation de la réponse GetFeatureInfo

Maintenant que vous comprenez mieux la réponse XML de GetFeatureInfo et les modèles XSLT, vous pouvez explorer différentes façons de personnaliser la réponse WMS GetFeatureInfo.

Modification des modèles XSLT par défaut

La première façon d’y parvenir consiste à modifier physiquement les modèles XSLT. Par exemple, si vous ouvrez le modèle HTML featureinfo_text_html.xsl dans un éditeur de texte et remplacez la balise <Style> par le code XML suivant, la couleur de la légende de la table passera au rouge.

Exemple XML

<style type="text/css">
          table, th, td {
            border:1px solid #e5e5e5;
            border-collapse:collapse;
            font-family: arial;                      font-size: 80%;            
            color: #333333          }                       th, td {
            valign: top;
            text-align: center;
          }                    th {
            background-color: #ffb7b7          }
          caption {
            border:1px solid #e5e5e5;
            border-collapse:collapse;
            font-family: arial;                      font-weight: bold;
            font-size: 80%;                  text-align: left;      
            color: #333333;              }
        </style>

Exemple de réponse

Réponse GetFeatureInfo HTML avec légende de table rouge

Cependant, si vous souhaitez modifier ces modèles, cela affectera directement tout WMS publié via ArcGIS Server. Pour cette raison, évitez de mettre dans les modèles toute logique spécifique au service de carte.

Utilisation du paramètre modèle_xsl

Une autre méthode de personnalisation de la réponse GetFeatureInfo consiste à remplacer le comportement des modèles XSLT par défaut à l’aide du paramètre modèle_xsl. Le modèle_xsl est un paramètre propre à ESRI que vous pouvez définir dans l’URL d’un fichier modèle XSLT. Lorsque le modèle est précisé dans la chaîne de l’URL, le WMS remplacera le modèle par défaut et utilisera le modèle que vous avez précisé. Si vous avez déjà créé un modèle personnalisé, il s'agit de la meilleure méthode pour utiliser votre modèle dans la réponse GetFeatureInfo.

Remarque :

Lorsque vous utilisez le paramètre du modèle_xsl, votre modèle XSLT n’a pas à suivre la même convention de désignation que les modèles par défaut, mais il doit être accessible via une URL. En précisant un chemin d’accès local ou un chemin UNC entraînera l’échec de la requête.

Vous trouverez ci-dessous un exemple d’une requête GetFeatureInfo avec le paramètre modèle_xsl :

http://gisserver.domain.com/arcgis/services/ihs_petroleum/MapServer/WMSServer?&service=WMS&version=1.1.1&request=GetFeatureInfo&layers=pipelines&query_layers=pipelines&styles=&bbox=47.119661,28.931116,48.593202,29.54223&srs=EPSG:4326&feature_count=10&x=389&y=120&height=445&width=1073&info_format=text/plain&xsl_template=http://server/resources/xsl/featureinfo_application_geojson.xsl

L’URL ci-dessus renvoie vers un modèle externe qui remplace le modèle par défaut. Le modèle XML personnalisé se présente comme suit :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:esri_wms="http://www.esri.com/wms" xmlns="http://www.esri.com/wms">
  <xsl:output method="text" indent="yes" encoding="ISO-8859-1"/>
  <xsl:template match="/">
    {
    "type": "FeatureCollection",    "spatialReference": { "wkid": <xsl:value-of select="esri_wms:FeatureInfoResponse/esri_wms:FeatureInfoCollection/esri_wms:FeatureInfo/esri_wms:CRS"/> },    "features": [<xsl:for-each select="esri_wms:FeatureInfoResponse/esri_wms:FeatureInfoCollection/esri_wms:FeatureInfo">
      {
        "type": "Feature",		<xsl:if test="count(esri_wms:Field/esri_wms:FieldGeometry/*) > 0">
        "geometry": {
          <xsl:for-each select="esri_wms:Field/esri_wms:FieldGeometry">
            <xsl:for-each select="esri_wms:Point">"type": "Point",              "coordinates": [<xsl:value-of select="."/>]</xsl:for-each>
            <xsl:for-each select="esri_wms:Multipoint">"type": "MultiPoint",    "coordinates": [<xsl:for-each select="esri_wms:Point">[<xsl:value-of select="."/>]<xsl:if test = "position() != last()">,</xsl:if></xsl:for-each>]</xsl:for-each>
            <xsl:for-each select="esri_wms:Polyline">"type": "MultiLineString", "coordinates": [<xsl:for-each select="esri_wms:Path"> [<xsl:for-each select="esri_wms:Point">[<xsl:value-of select="."/>]<xsl:if test = "position() != last()">,</xsl:if></xsl:for-each>]<xsl:if test = "position() != last()">,</xsl:if></xsl:for-each>]</xsl:for-each>
            <xsl:for-each select="esri_wms:Polygon">"type": "Polygon",          "coordinates": [<xsl:for-each select="esri_wms:Ring"> [<xsl:for-each select="esri_wms:Point">[<xsl:value-of select="."/>]<xsl:if test = "position() != last()">,</xsl:if></xsl:for-each>]<xsl:if test = "position() != last()">,</xsl:if></xsl:for-each>]</xsl:for-each>
          </xsl:for-each>
      },    </xsl:if>
    "properties": {<xsl:for-each select="esri_wms:Field">
          "<xsl:value-of select="esri_wms:FieldName"/>": "<xsl:value-of select="esri_wms:FieldValue"/>"<xsl:if test="position() != last()">,</xsl:if>
        </xsl:for-each>
        },        "layerName": "<xsl:value-of select="../@layername"/>"	      }<xsl:if test="position() != last()">,</xsl:if>
      </xsl:for-each>
    ]  }
  </xsl:template>
  </xsl:stylesheet>

Le modèle a été créé pour que le WMS renvoie ses réponses GetFeatureInfo en texte brut GeoJSON avec une géométrie de type entité plutôt que le format HTML par défaut. GeoJSON peut être analysé par de nombreuses bibliothèques JavaScript, ce qui vous permet d'intégrer vos réponses à des pages Web dans un format facile à lire.

Vous trouverez ci-dessous un exemple de réponse GetFeatureInfo au format GeoJSON en tant que source de données d'une grille Ext.Grid dans une application de cartes Web OpenLayers.

Réponse GeoJSON GetFeatureInfo comme source de données d’un Ext.Grid dans une application de carte Web OpenLayers

En s'appuyant sur l'exemple précédent, l'exemple de modèle ci-dessous peut être utilisé pour incorporer un objet vidéo dans la réponse :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:esri_wms="http://www.esri.com/wms" xmlns="http://www.esri.com/wms">
  <!--
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  -->      <xsl:output 
    method="html"     indent="yes" 
    encoding="UTF-8"     omit-xml-declaration="yes"/> 
  <xsl:template match="/">      <!--<html>
      <head>-->
        <style type="text/css">
          table, th, td {
            border:1px solid #e5e5e5;
            border-collapse:collapse;
            font-family: arial;                      font-size: 80%;            
            color: #333333          }                       th, td {
            valign: top;
            text-align: center;
          }                    th {
            background-color: #aed7ff;
          }
          caption {
            border:1px solid #e5e5e5;
            border-collapse:collapse;
            font-family: arial;                      font-weight: bold;
            font-size: 80%;                  text-align: left;      
            color: #333333;
            background-color: #aed7ff;                      }
        </style>
          <!--</head>
      <body>-->        <div>        
        <xsl:for-each select="esri_wms:FeatureInfoResponse/esri_wms:FeatureInfoCollection">                                        <table width="100%" cellpadding="0" cellspacing="0" border="1">
            <tbody>                                        <caption>layer names: '<xsl:value-of select="@layername"/>'</caption>
              <xsl:for-each select="esri_wms:FeatureInfo[1]/esri_wms:Field">
                <xsl:variable name="fieldName" select="esri_wms:FieldName"/>
                <xsl:variable name="fieldValue" select="esri_wms:FieldValue"/>                                              <xsl:if test="$fieldName = 'PLOT_SYMBOL_GROUP'">                  
                  <xsl:choose>
                    <xsl:when test="$fieldValue = 2">                                            <tr>
                        <td>
                          wiki link                        </td>
                        <td>
                          <a target="_blank">
                            <xsl:attribute name="href">
                              http://en.wikipedia.org/wiki/Oil_well                            </xsl:attribute>
                            Oil Well                          </a>                          </td>
                      </tr>                                            <tr>
                        <td>
                          video                        </td>
                        <td>
                          <div>
                          <object width="425" height="344">
                            <param name="movie" value="http://www.youtube.com/v/HVxsbb1lDsQ"></param>
                            <param name="allowFullScreen" value="true"></param>
                            <param name="allowscriptaccess" value="always"></param>
                            <embed src="http://www.youtube.com/v/HVxsbb1lDsQ" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed>
                          </object>
                          </div>
                        </td>
                      </tr>
                    </xsl:when>                                          </xsl:choose>                    
                </xsl:if>                                                  </xsl:for-each>                              
            </tbody>
          </table>                  </xsl:for-each>
      </div>
    <!--</body>
    </html>-->
  </xsl:template>

Vous trouverez ci-dessous un exemple de la réponse GetFeatureInfo avec vidéo incorporée dans une application de cartes Web OpenLayers.

Réponse GetFeatureInfo avec vidéo intégrée dans une application de carte Web OpenLayers

Celle-ci est un exemple plus complet qui personnalise considérablement la réponse GetFeatureInfo pour intégrer un extrait de code JavaScript. Le code s’appuie sur l’application Web du plug-in Google Earth. N’oubliez pas que dans ce modèle XSLT, il y a une logique spécifique à un service WMS particulier. Par conséquent, ce modèle doit toujours être référencé via le paramètre modèle_xsl. Il ne doit pas devenir le modèle par défaut.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:esri_wms="http://www.esri.com/wms" xmlns="http://www.esri.com/wms">
  <!--
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  -->      <xsl:output 
    method="html"     indent="yes" 
    encoding="UTF-8"     omit-xml-declaration="yes"/> 
  <xsl:template match="/">      <!--<html>
      <head>-->
        <style type="text/css">
          table, th, td {
            border:1px solid #e5e5e5;
            border-collapse:collapse;
            font-family: arial;                      font-size: 80%;            
            color: #333333          }                       th, td {
            valign: top;
            text-align: center;
          }                    th {
            background-color: #aed7ff;
          }
          caption {
            border:1px solid #e5e5e5;
            border-collapse:collapse;
            font-family: arial;                      font-weight: bold;
            font-size: 80%;                  text-align: left;      
            color: #333333;
            background-color: #aed7ff;                      }
        </style>
          <!--</head>
      <body>-->        <div>        
        <xsl:for-each select="esri_wms:FeatureInfoResponse/esri_wms:FeatureInfoCollection">                                        <table width="100%" cellpadding="0" cellspacing="0" border="1">
            <tbody>                                        <caption>layer names: '<xsl:value-of select="@layername"/>'</caption>
              <xsl:for-each select="esri_wms:FeatureInfo[1]/esri_wms:Field">
                <xsl:variable name="fieldName" select="esri_wms:FieldName"/>
                <xsl:variable name="fieldValue" select="esri_wms:FieldValue"/>                                <xsl:if test="$fieldName = 'WGS84_LONGITUDE'">
                  <xsl:variable name="lon" select="esri_wms:FieldValue"/>
                  <tr>
                    <td>lon</td>
                    <td><xsl:value-of select="$lon"/></td>
                    <script type="text/javascript">
                      popup_lon = '<xsl:value-of select="$lon"/>';
                    </script>
                  </tr>
                </xsl:if>
                <xsl:if test="$fieldName = 'WGS84_LATITUDE'">
                  <xsl:variable name="lat" select="esri_wms:FieldValue"/>
                  <tr>
                    <td>lat</td>
                    <td><xsl:value-of select="$lat"/></td>
                    <script type="text/javascript">
                      popup_lat = '<xsl:value-of select="$lat"/>';
                    </script>
                  </tr>
                </xsl:if>                                                                                              <xsl:if test="$fieldName = 'PLOT_SYMBOL_GROUP'">                  
                  <xsl:choose>                                        <xsl:when test="$fieldValue = 14">                                                                                      
                      <tr>
                        <td>
                          3d map                        </td>
                        <td>
                          <div id="map3d" style="width:384px;height:256px;"></div>
                          <script type="text/javascript">
                            google.earth.createInstance(                              'map3d',                               function(instance) {
                                ge = instance;
                                ge.getWindow().setVisibility(true);
                                                                var kmlStr = ''                                        
                                  + '<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">'                                  + '<gx:Tour>'                                  + '<gx:Playlist><gx:FlyTo>'                                  + '<gx:duration>20.0</gx:duration>'                                  + '<LookAt>'                                  + '<longitude>' + popup_lon + '</longitude>'                                  + '<latitude>' + popup_lat + '</latitude>'                                  + '<altitude>0</altitude>'                                  + '<heading>0</heading>'                                  + '<tilt>0</tilt>'                                  + '<range>500</range>'                                  + '<altitudeMode>relativeToGround</altitudeMode>'                                  + '</LookAt>'                                  + '</gx:FlyTo></gx:Playlist>'                                  + '</gx:Tour>'                                  + '</kml>';
                                                                        var kmlObj = ge.parseKml(kmlStr);
                                ge.getTourPlayer().setTour(kmlObj);
                                ge.getTourPlayer().play();                                                              }, 
                              function() {
                                                              }
                            );
                          </script>
                        </td>
                      </tr>
                    </xsl:when>                    </xsl:choose>                    
                </xsl:if>                                                  </xsl:for-each>                              
            </tbody>
          </table>                  </xsl:for-each>
      </div>
    <!--</body>
    </html>-->
  </xsl:template>