XSLT WFS output format module

The xslt module for GeoServer is a WFS output format generator which brings togheter a base output, such as GML, and a XSLT 1.0 style sheet to generate a new textual output format of user choosing.

The configuration for this output format can be either performed directly on disk, or via a REST API.

Manual configuration

All the configuration for the output resides in the $GEOSERVER_DATA_DIR/wfs/transform folder, which is going to be created on startup when missing if the XSLT output format has been installed in GeoServer.

Each XSLT transformation must be configured with its own xml file in the $GEOSERVER_DATA_DIR/wfs/transform folder, which in turn points to a xslt file for the transformation. While the names can be freeform, it is suggested to follow a simple naming convention:

  • <mytransformation>.xml for the xml config file
  • <mytransformation>.xslt for the xslt tile

Transformations can be either global, and thus applicable to any feature type, or type specific, in which case the transformation knows about the specific attributes of the transformed feature type.

Global transformation example

Here is an example of a global transformation setup. The $GEOSERVER_DATA_DIR/wfs/transform/global.xml file will look like:

<transform>
  <sourceFormat>text/xml; subtype=gml/2.1.2</sourceFormat>
  <outputFormat>HTML</outputFormat>
  <outputMimeType>text/html</outputMimeType>
  <fileExtension>html</fileExtension>
  <xslt>global.xslt</xslt>
</transform>

Here is an explanation of each element:

  • sourceFormat (mandatory): the output format used as the source of the XSLT transformation
  • outputFormat (mandatory): the output format generated by the transformation
  • outputMimeType (optional): the mime type for the generated output. In case it’s missing, the outputFormat is assumed to be a mime type and used for the purpose.
  • fileExtension (optional): the file extension for the generated output. In case it’s missing txt will be used.
  • xslt (mandatory): the name of XSLT 1.0 style sheet used for the transformation

The associated XSLT file will be $GEOSERVER_DATA_DIR/wfs/transform/global.xslt folder, and it will be able to transform any GML2 input into a corresponding HTML file. Here is an example:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:wfs="http://www.opengis.net/wfs"
  xmlns:tiger="http://www.census.gov" xmlns:gml="http://www.opengis.net/gml"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
      <body>
      <xsl:for-each select="wfs:FeatureCollection/gml:featureMember/*">
        <h2><xsl:value-of select="@fid"/></h2>
        <table border="1">
          <tr>
            <th>Attribute</th>
            <th>Value</th>
          </tr>
            <!-- [not(*)] strips away all nodes having
                 children, in particular, geometries -->
            <xsl:for-each select="./*[not(*)]">
            <tr>
              <td>
                <xsl:value-of select="name()" />
              </td>
              <td>
                <xsl:value-of select="." />
              </td>
            </tr>
            </xsl:for-each>
        </table>
     </xsl:for-each>
     </body>
   </html>
  </xsl:template>
</xsl:stylesheet>

Type specific transformations

Type specific transformations can refer to a specific type and leverage its attributes directly. While not required, it is good practice to setup a global transformation that can handle any feature type (since the output format is declared in the capabilities document as being general, not type specific) and then override it for specific feature types in order to create special transformations for them.

Here is an example of a transformation declaration that is type specific, that will be located at $GEOSERVER_DATA_DIR/wfs/transform/html_bridges.xml

<transform>
  <sourceFormat>text/xml; subtype=gml/2.1.2</sourceFormat>
  <outputFormat>HTML</outputFormat>
  <outputMimeType>text/html</outputMimeType>
  <fileExtension>html</fileExtension>
  <xslt>html_bridges.xslt</xslt>
  <featureType>
    <id>cite:Bridges</id>
  </featureType>
</transform>

The extra featureType element associates the transformation to the specific feature type

The associated xslt file will be located at $GEOSERVER_DATA_DIR/wfs/transform/html_bridges.xslt and will leveraging knowlegde about the input attributes:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:wfs="http://www.opengis.net/wfs"
  xmlns:cite="http://www.opengis.net/cite" xmlns:gml="http://www.opengis.net/gml"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
      <body>
        <h2>Bridges</h2>
        <xsl:for-each
            select="wfs:FeatureCollection/gml:featureMember/cite:Bridges">
        <ul>
          <li>ID: <xsl:value-of select="@fid" /></li>
          <li>FID: <xsl:value-of select="cite:FID" /></li>
          <li>Name: <xsl:value-of select="cite:NAME" /></li>
        </ul>
        <p/>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Note

While writing the XSLT always remember to declare all prefixes used in the sheet in the stylesheet element, otherwise you might encounter hard to understand error messages

A specific feature type can be associated to multiple output formats. While uncommon, the same xslt file can also be associated to multiple feature types by creating multiple xml configuration files, and associating a different feature type in each.

Rest configuration

Transformations can be created, updated and deleted via the REST api (normally, this requires administrator privileges). Each transformation is represented with the same XML format used on disk, but with two variants:

  • a new name attribute appears, which matches the XML file name
  • the featureType element contains also a link to the resource representing the feature type in the REST config tree

For example:

<transform>
  <name>test</name>
  <sourceFormat>text/xml; subtype=gml/2.1.2</sourceFormat>
  <outputFormat>text/html</outputFormat>
  <fileExtension>html</fileExtension>
  <xslt>test-tx.xslt</xslt>
  <featureType>
    <name>tiger:poi</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/cite/datastores/cite/featuretypes/bridges.xml" type="application/xml"/>
  </featureType>
</transform>

Here is a list of resources and the HTTP methods that can be used on them.

/rest/services/wfs/transforms[.<format>]

Method Action Return Code Formats Default Format Parameters
GET List all available transforms 200 HTML, XML, JSON HTML  
POST Add a new transformation 201, with Location header XML, JSON   name, sourceFormat, outputFormat, outputMimeType
PUT Update global settings 200 XML, JSON    
DELETE   405      

The POST method can be used to create a transformation in two ways:

  • if the content type used is application/xml the server will assume a <transform> definition is being posted, and the XSLT will have to be uploaded separately using a PUT request with content type application/xslt+xml against the transformation resource
  • if the content type used is application/xslt+xml the server will assume the XSLT itself is being posted, and the name, sourceFormat, outputFormat, outputMimeType query parameters will be used to fill in the transform configuration instead

/rest/services/wfs/transforms/<transform>[.<format>]

Method Action Return Code Formats Default Format
GET Returns the transformation 200 HTML, XML, XSLT HTML
POST   405    
PUT Updates either the transformation configuration, or its XSLT, depending on the mime type used 200 XML, XSLT  
DELETE Deletes the transformation 200    

The PUT operation behaves differently depending on the content type used in the request:

  • if the content type used is application/xml the server will assume a <transform> definition is being sent and will update it
  • if the content type used is application/xslt+xml the server will assume the XSLT itself is being posted, as such the configuration won’t be modified, but the XSLT associated to it will be overwritten instead