/
Developing a XSLT Transformer

Developing a XSLT Transformer

Prerequisites

  1. Understand the desired component for development as described in the DDF Catalog section.
  2. Have an IDE and the ability to create OSGi bundles.
  3. Understand the Use of the Whiteboard Design Pattern section and how to publish services to the OSGi service registry.

XSLT Transformer Framework

The XSLT Transformer Framework allows developers to create light-weight Query Response Transformers and Metacard Transformers using only a bundle header and XSLT files.  The XSLT Transformer Framework registers bundles, following the XSLT Transformer Framework bundle pattern, as new transformer services.  The  service-xslt-transformer feature is part of the DDF core.  

Examples

Examples of XSLT Transformers using the XSLT Transformer Framework include service-atom-transformer and service-html-transformer, found in the services folder of the source code trunk.

Implement XSLT Transformer

  1. Create a new Maven Project.
  2. Configure the POM to create a bundle using the Maven Bundle Plugin.
    1. Add the transform output MIME type to the bundle headers.
  3. Add XSLT files.

Bundle POM Configuration

Configure the Maven project to create an OSGi bundle using the maven-bundle-plugin.  Change the DDF-Mime-Type to match the MIME type of the transformer output.

Example POM file
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <DDF-Mime-Type>[[Transform Result MIME Type]]</DDF-Mime-Type>
                    <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                    <Import-Package />
                    <Export-Package />
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>
...

Including XSLT

The XSLT Transformer Framework will scan for XSLT files inside a bundle.  The XSLT file must have a .xsl or .xslt file in the correct directory location relative to the root of the bundle.  The path depends on if the XSLT will act as a Metacard TransformerQuery Response Transformer, or both.  The name of the XSLT file will be used as the transformer's shortname.

XSLT File Bundle Path Patterns
// Metacard Transformer
<bundle root>
    /OSGI-INF
        /ddf
            /xslt-metacard-transformer
                /<transformer shortname>.[xsl|xslt]
 
// Query Response Transformer 
<bundle root>
    /OSGI-INF
        /ddf
            /xslt-response-queue-transformer
                /<transformer shortname>.[xsl|xslt]

The XSLT file has access to Metacard or Query Reponse XML data depending on which folder the XSLT file is located.  The Metacard XML format will depend on the metadata schema used by the Catalog Provider.

For Query Response XSLT Transformers, the available XML data for XSLT transform has the following structure:

Query Response XML
<results>
    <metacard>
        <id>[[Metacard ID]]</id>
        <score>[[Relevance score]]</score>
        <distance>[[Distance from query location]]</distance>
        <site>[[Source of result]]</site>
        <type qualifier="type">[[Type]]</type>
        <updated>[[Date last updated]]</updated>
        <geometry>[[WKT geometry]]</geometry>
        <document>
            [[Metacard XML]]
        </document>
    </metacard>
    ...
</results>

The XSLT file has access to additional parameters.  The Map<String, Serializable> arguments from the transform method parameters is merged with the available XSLT parameters.

  • Query Response Transformers
    • grandTotal - total result count 
  • Metacard Transformers
    • id - Metacard ID
    • siteName - Source ID
    • services - list of displayable titles and URLs of available Metacard transformers

RSS Example

Create a Maven project named service-rss-transformer.  Add the following to its POM file.

 

Example RSS POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <packaging>bundle</packaging>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>services</artifactId>
    <groupId>ddf</groupId>
    <version>[[DDF release version]]</version>
  </parent>
  <groupId>ddf.services</groupId>
  <artifactId>service-rss-transformer</artifactId>
 
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <DDF-Mime-Type>application/rss+xml</DDF-Mime-Type>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Import-Package />
            <Export-Package />
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
Line #Comment
8Use the current release version.
21Set the MIME type to the RSS MIME type.

Add service-rss-transformer/src/main/resources/OSGI-INF/ddf/xslt-response-queue-transformer/rss.xsl. The transformer will be a Query Response Transformer with the shortname rss based on the XSL filename and path.  Add the following XSL to the new file.

Example RSS XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ddms="http://metadata.dod.mil/mdr/ns/DDMS/2.0/"
 xmlns:gml="http://www.opengis.net/gml" exclude-result-prefixes="xsl ddms gml">
 
  <xsl:output method="xml" version="1.0" indent="yes" />
 
  <xsl:param name="grandTotal" />
  <xsl:param name="url" />
 
  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>
 
  <xsl:template match="results">
    <rss version="2.0">
      <channel>
      <title>Query Results</title>
      <link><xsl:value-of select="$url" disable-output-escaping="yes" /></link>
      <description>Query Results of <xsl:value-of select="count(//metacard)" /> out of <xsl:value-of select="$grandTotal" /></description>
      <xsl:for-each select="metacard/document">
        <item>
          <guid>
            <xsl:value-of select="../id" />
          </guid>
          <title>
            <xsl:value-of select="Data/title" />
          </title>
          <link>
            <xsl:value-of select="substring-before($url,'/services')" /><xsl:text>/services/catalog/</xsl:text><xsl:value-of select="../id" /><xsl:text>?transform=html</xsl:text>
          </link>
          <description>
            <xsl:value-of select="//description" />
          </description>
          <author>
            <xsl:choose>
              <xsl:when test="Data/creator">
                <xsl:value-of select="Resource/creator//name" />
              </xsl:when>
              <xsl:when test="Data/publisher">
                <xsl:value-of select="Data/publisher//name" />
              </xsl:when>
              <xsl:when test="Data/unknown">
                <xsl:value-of select="Data/unknown//name" />
              </xsl:when>
            </xsl:choose>
          </author>
          <xsl:if test=".//@posted" >
            <pubDate>
              <xsl:value-of select=".//posted" />
            </pubDate>
          </xsl:if>
          </item>
        </xsl:for-each>
      </channel>
    </rss>
  </xsl:template>
</xsl:stylesheet> 
Line #Comment
8-9Example of using additional parameters and arguments.
15Example of using the Query Response XML data.
21,27Example of using the Metacard XML data.