WMS サービスは GetCapabilities、GetMap、GetStyles などの一連のオペレーションをサポートし、サービスの URL にパラメーターを追加することでクライアント アプリケーションがサービスを操作できるようにします。GetFeatureInfo オペレーションはこれらと同じ方法で動作し、マップで検索されたフィーチャの属性を HTML、XML、テキストなどのさまざまな形式で返すために設計されています。
たとえば、GetFeatureInfo リクエストとデフォルトの HTML 形式によるレスポンスは次のようになります。
リクエスト
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&
レスポンス

多くの場合はデフォルトの HTML、XML、またはテキスト形式のレスポンスが適切となりますが、レスポンスの形式またはスキーマを状況に応じてカスタマイズし、特定のビジネス ロジックを実行することもできます。たとえば、相互運用性の目的で、フィーチャの情報を GML や GeoJSON などの標準的なスキーマで取得することもできます。
XSLT テンプレート
XSLT (Extensible Stylesheet Language Transformation) テンプレートを使用すると、WMS GetFeatureInfo レスポンスから判読可能な出力を生成できます。たとえば、サーバーに WMS GetFeatureInfo リクエストを送信すると、サーバーはリクエストされたフィーチャを XML 形式で返します。XSLT テンプレートは、XML を HTML やテキストなどの指定された形式に変換し、最終的なレスポンスを判読できるようにします。
WMS GetFeatureInfo XML レスポンスと ArcGIS Server のインストール時に提供されるデフォルトの XSLT テンプレートを検証すると、GetFeatureInfo レスポンスのカスタマイズ方法を理解する際に役立ちます。以下のセクションでは、それぞれについて詳しく説明します。
GetFeatureInfo XML レスポンス
WMS サービスにおける GetFeatureInfo レスポンスの XML の例を示します。
<?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>
詳細は以下のとおりです。
- ルート タグの <FeatureInfoResponse> には、複数の <FeatureInfoCollection> エレメントが含まれる場合があります。
- 各 <FeatureInfoCollection> エレメントには、1 つの WMS レイヤーで識別されたすべてのフィーチャの属性フィールドと値が含まれます。
- 識別された 1 つのフィーチャの情報は、1 つの <FeatureInfo> タグ内に格納されます。フィールドごとに名前と値のペアが存在します。
- 空間参照情報は、各 <FeatureInfo> タグとともに格納されます。
- フィーチャ ジオメトリがある場合は、<FieldGeometry> タグ内に返されます。
- フィールド ジオメトリには、ポイント、マルチポイント、ポリライン、ポリゴン ジオメトリを格納できます。
デフォルトの XSLT テンプレート
ArcGIS Server には、WMS のケーパビリティ ファイルの一覧に表示されるサポートされる形式用に XSLT テンプレートが用意されています。たとえば、これらのテンプレートが格納されているディレクトリ (<ArcGIS Server インストール ディレクトリ>/Styles/WMS) を開くと、以下のテンプレートが見つかります。
- 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
名前からわかるように、各テンプレートはデフォルトの GetFeatureInfo レスポンスを判読可能な形式 (GeoJSON、テキスト、XML など) で生成するために使用されます。
このトピックの最初で例にあげた青色のキャプションが付いた HTML の表は、デフォルトの XSLT HTML テンプレートを使用して生成されています。また、レスポンスとして未処理の XML が必要な場合は、GetFeatureInfo リクエスト パラメーターの INFO_FORMAT を application/vnd.esri.wms_raw_xml に設定します。独自の XSLT テンプレートを作成する場合は、この方法を使用します。
GetFeatureInfo レスポンスのカスタマイズ
ここまでは GetFeatureInfo レスポンスの XML および XSLT テンプレートについて説明しました。続いて、WMS GetFeatureInfo レスポンスをカスタマイズする方法について説明します。
デフォルトの XSLT テンプレートの変更
GetFeatureInfo レスポンスをカスタマイズするための 1 つ目の方法は、XSLT テンプレートを物理的に変更することです。たとえば、featureinfo_text_html.xsl HTML テンプレートをテキスト エディターで開き、<Style> タグを次の XML で置き換えると、表のキャプションが赤色で表示されます。
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>
レスポンスの例

ただし、これらのテンプレートに対する変更は、ArcGIS Server を通して公開されるすべての WMS に直接影響します。このため、マップ サービスに固有のロジックをテンプレートに記述することは避けてください。
xsl_template パラメーターの使用
GetFeatureInfo レスポンスをカスタマイズする別の方法として、xsl_template パラメーターを使用してデフォルトの XSLT テンプレートの動作を無効にすることができます。xsl_template は、XSLT テンプレート ファイルの URL 内に設定できる Esri 独自のパラメーターです。テンプレートが URL 文字列で指定されている場合、WMS はデフォルトのテンプレートの代わりに指定されたテンプレートを使用します。すでに構築済みのカスタム テンプレートを GetFeatureInfo レスポンスで利用する場合は、この方法が最も適切です。
注意:
xsl_template パラメーターを使用する場合、XSLT テンプレートはデフォルトのテンプレートと同じ命名規則に従っている必要はありませんが、URL を通してアクセスできる必要があります。ローカル パスまたは ネットワーク共有を指定すると、リクエストは失敗します。
xsl_template パラメーターを使用した GetFeatureInfo リクエストの例を示します。
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
上の URL は、デフォルトのテンプレートの代わりに外部のテンプレートを参照します。カスタマイズしたテンプレートの XML は以下のようになります。
<?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>
テンプレートは、WMS が GetFeatureInfo レスポンスをデフォルトの HTML 形式ではなく、テキストの GeoJSON 形式でフィーチャ ジオメトリとともに返すように作成されています。GeoJSON は多くの JavaScript ライブラリで解析可能です。これを利用して、レスポンスを Web ページに読みやすい形式で統合できます。
次に示すのは、OpenLayers Web マップ アプリケーションで GetFeatureInfo GeoJSON レスポンスを Ext.Grid のデータ ソースとして使用する例です。

上のサンプルを基に、次に示すサンプル テンプレートを使用してレスポンスにビデオ オブジェクトを埋め込むことができます。
<?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>
OpenLayers Web マップ アプリケーションのビデオが埋め込まれた GetFeatureInfo レスポンスの例を示します。

GetFeatureInfo レスポンスをさらにカスタマイズして、JavaScript コード スニペットを埋め込んだ少し複雑な例を示します。コードは、Google Earth プラグイン Web アプリケーションでツアーを再生します。この XSLT テンプレートには、特定の WMS サービスに固有のロジックが含まれていることに注意してください。したがって、このテンプレートは常に xsl_template パラメーターを使用して参照します。このテンプレートをデフォルト テンプレートに設定しないでください。
<?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>