Personalizar una respuesta GetFeatureInfo de WMS

Los servicios WMS admiten una serie de operaciones, como GetCapabilities, GetMap, GetStyles y así sucesivamente, las cuales permiten que las aplicaciones del cliente trabajen con el servicio mediante la incorporación de parámetros a la dirección URL del servicio. La operación GetFeatureInfo funciona de la misma manera y está diseñada para devolver los atributos de entidades que se han consultado en un mapa en diferentes formatos, tales como HTML, XML y texto sin formato.

Por ejemplo, la siguiente es una solicitud GetFeatureInfo junto con su respuesta en el formato HTML predeterminado:

Solicitud

http://myserver/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&

Respuesta

Respuesta GetFeatureInfo HTML predeterminada

En muchos casos, la respuesta predeterminada de HTML, XML o texto sin formato es adecuada, pero pueden surgir inconvenientes cuando desee personalizar el esquema o formato de respuesta para ejecutar una lógica de negocios específica. Por ejemplo por razones de interoperabilidad, quizá desee obtener la información de la entidad en un esquema estándar como GML o GeoJSON.

Plantillas XSLT

Las plantillas de transformaciones de lenguaje de estilo extensible (XSLT) son una forma de generar una salida legible desde la respuesta GetFeatureInfo de WMS. Por ejemplo, cuando envía una solicitud GetFeatureInfo de WMS al servidor, el servidor responde con las entidades solicitadas en formato XML. La plantilla XSLT entonces hace el trabajo de "traducir" el XML a un formato específico, como HTML o texto sin formato, lo que hace que la respuesta final sea legible.

La revisión de la respuesta XML GetFeature de WMS y las plantillas XSLT predeterminadas que vienen con la instalación de ArcGIS for Server le ayudará a obtener una mejor comprensión de cómo personalizar una respuesta GetFeatureInfo. Las siguientes secciones analizan cada una con más detalle.

Respuesta XML GetFeature

A continuación hay un ejemplo de XML de una respuesta GetFeatureInfo en un servicio de 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:FeatureInfo>     ...     <!-- there could be more <esri_wms:FeatureInfo> -->     ...   </esri_wms:FeatureInfoCollection>   ...   <!-- there could be more <esri_wms:FeatureInfoCollection> -->   ... </esri_wms:FeatureInfoResponse>

Observe estos detalles:

  • La etiqueta raíz <FeatureInfoResponse> puede contener varios elementos <FeatureInfoCollection>.
  • Cada elemento <FeatureInfoCollection> contiene los campos de atributos y valores de todas las entidades identificadas desde una única capa WMS.
  • La información para una única entidad identificada está incluida en una etiqueta <FeatureInfo>. Observe el par nombre-valor para cada campo.

Plantillas XSLT predeterminadas

ArcGIS for Server viene con plantillas XSLT para los formatos compatibles enumerados en los archivos de recursos de WMS. Por ejemplo, si desea abrir el directorio de estas plantillas en <ArcGIS 10.1 for Server installation location>/Styles/WMS, verá lo siguiente:

  • 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

Como sus nombres implican, cada plantilla se utiliza para producir una respuesta GetFeatureInfo predeterminada en un formato legible, como GeoJSON, texto sin formato y XML.

La tabla HTML de ejemplo con el título que aparece al principio de este tema se produjo usando la plantilla XSLT HTML predeterminada. Como alternativa, si desea obtener el XML como la respuesta, puede establecer el parámetro de solicitud GetFeatureInfo INFO_FORMAT para application/vnd.esri.wms_raw_xml. Puede utilizar este método para crear su propia plantilla XSLT.

Personalizar la respuesta GetFeatureInfo

Ahora que tiene una mejor comprensión de las plantillas XML y XSLT de respuesta GetFeatureInfo, puede explorar un par de maneras de personalizar la respuesta GetFeatureInfo de WMS.

Modificar las plantillas XSLT predeterminadas

La primera forma de hacer esto es modificar físicamente las plantillas XSLT. Por ejemplo, si abre la plantilla HTML featureinfo_text_html. xsl en un editor de texto y reemplaza la etiqueta <Style> con el siguiente XML, verá el título de la tabla cambiará a color rojo:

Ejemplo 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>

Ejemplo de respuesta

HTML GetFeatureInfo con título de tabla rojo

Sin embargo, si decide modificar estas plantillas, afectará directamente a cualquier WMS publicado a través de ArcGIS for Server. Por esta razón, evitar intentar incluir cualquier lógica específica del servicio de mapas en las plantillas.

Usar el parámetro xslt_template

Otro método de personalizar la respuesta GetFeatureInfo es anular el comportamiento de las plantillas XSLT predeterminadas con el parámetro xslt_template. El xslt_template es un parámetro específico de Esri que puede establecer en la dirección URL de un archivo de plantilla XSLT. Cuando la plantilla se especifica en la cadena de la dirección URL, WMS anulará la plantilla predeterminada y utilizará la plantilla que especificó. Si ya creó una plantilla personalizada, este es el método más apropiado para utilizar la plantilla en la respuesta GetFeatureInfo.

NotaNota:

Cuando se utiliza el parámetro xslt_template, su plantilla XSLT no tiene que seguir la misma convención de nomenclatura que las plantillas predeterminadas, pero no debe estar disponible a través de una dirección URL. Especificar una ruta local o un ruta UNC provocará la solicitud al fracaso.

A continuación se muestra un ejemplo de una solicitud GetFeatureInfo con el parámetro xslt_template:

http://myserver/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

La dirección URL anterior hace referencia a una plantilla externa que anula la plantilla predeterminada. La plantilla personalizada XML es la siguiente:

<?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",   "features": [<xsl:for-each select="esri_wms:FeatureInfoResponse/esri_wms:FeatureInfoCollection/esri_wms:FeatureInfo">     {       "type": "Feature",       "properties":          {<xsl:for-each select="esri_wms:Field">                             "<xsl:value-of select="esri_wms:FieldName"/>":"<xsl:value-of select="esri_wms:FieldValue"/>",</xsl:for-each>         },       "layerName":"<xsl:value-of select="../@layername"/>"       },</xsl:for-each>   ] }   </xsl:template> </xsl:stylesheet>

La plantilla se creó para hacer que WMS devuelva sus respuestas GetFeatureInfo en texto sin formato GeoJSON en lugar del formato HTML predeterminado. GeoJSON puede analizarse mediante muchas bibliotecas JavaScript, lo que permite que integre sus respuestas con páginas Web en un formato fácil de leer.

A continuación se muestra un ejemplo de una respuesta GetFeatureInfo GeoJSON como una fuente de datos de una Ext.Grid en una aplicación de mapa Web OpenLayers:

Respuesta GetFeatureInfo GeoJSON como una fuente de datos de una Ext.Grid en una aplicación de mapa Web OpenLayers

Para construir en el ejemplo anterior, la siguiente plantilla de ejemplo se puede utilizar para insertar un objeto de vídeo en la respuesta:

<?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>

A continuación se presenta una respuesta GetFeatureInfo con un vídeo integrado a la aplicación de mapa Web OpenLayers:

Respuesta GetFeatureInfo con un vídeo integrado en una aplicación de mapa Web OpenLayers

El siguiente es un ejemplo más completo que personaliza grandemente la respuesta GetFeatureInfo para incorporar un fragmento de código JavaScript. El código reproduce un recorrido en la aplicación Web del plug-in Google Earth. Tenga en cuenta que en esta plantilla XSLT, hay una lógica específica de un servicio WMS específico. Por lo tanto, siempre se debe hacer referencia a esta plantilla mediante el parámetro xslt_template. No debe ser la plantilla predeterminada.

<?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>

9/11/2013