XSLT stylesheet : How to

In this chapter we will not describe how to write XSLT stylesheets, but instead, comment very briefly an exsiting one, and explain a particular part of our business : how to generate references for the future edition.

1. Example

Open the stylesheet genericHorizontal.xsl shipped with TAXI located in editor/XML/Generic. This stylesheet is used to transform any XML document to a GRP document. On the graphic, a tree will be drawn. Each node of this tree will represent a tag of the XML source document. Attributes and their value of the XML source document tags will be drawn next to the node that represents the tag.

What we need to do :

  1. Generate the structure of boxes,
  2. Generate the links to connect the nodes,
  3. Generate the references to allow edition.

This is exactly what we do with the template that catches the special root tag / :

    <xsl:template match="/">
      <grp>
        <!-- Génération de la structure de boîtes -->
        <xsl:apply-templates select="*" mode="box"/>

        <!-- Génération des liens -->
        <xsl:apply-templates select="*" mode="link"/>

        <!-- Génération des références -->
        <xsl:apply-templates select="*" mode="reference"/>
      </grp>
    </xsl:template>
  

We place the opening tag <grp>, then create the structure of boxes, the links, and the references. We terminate by placing the closing tag </grp>.

The structure boxes is generated by the following template :

    <xsl:template match="*" mode="box">
      <hbox>
        <xsl:attribute name="id">
          <xsl:value-of select="generate-id()"/>
          <xsl:text>tag1</xsl:text>
        </xsl:attribute>

        ...


      </hbox>
    </xsl:template>
  

The links are generated by the following template :

    <xsl:template match="*" mode="link">
      <!-- Liens entre les balises -->
      <!-- On ne trace pas de lien entre / et la racine (/ n'a pas de nom) -->
      <xsl:if test="name(..)">

        ...

      </xsl:if>

      <xsl:apply-templates select="*" mode="link"/>
    </xsl:template>
  

The references are generated by the following template :

    <xsl:template match="*" mode="reference">
      <reference>
        <xsl:attribute name="source">
          <xsl:value-of select="java:xml.XPointer.getXPointer(.)"/>
        </xsl:attribute>

        <xsl:attribute name="target">
          <xsl:value-of select="generate-id()"/>
          <xsl:text>tag1</xsl:text>
        </xsl:attribute>
      </reference>

      <xsl:apply-templates select="*" mode="reference"/>
    </xsl:template>
  

2. How to generate References

If not already done, open the stylesheet genericHorizontal.xsl shipped with TAXI located in editor/XML/Generic.

At the very top of this stylesheet, you will notice that the root tag <xsl:stylesheet> contains a namespace for Java :

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:java="http://xml.apache.org/xslt/java"
                    version="1.0">
  

This namespace is mandatory as we will call some Java code to generate the attribute source of the references (the value of this attribute is a XPointer).

Here is how are generated references in the stylesheet editor/XML/Generic/genericHorizontal.xsl :

    <xsl:template match="*" mode="reference">
      <reference>
        <xsl:attribute name="source">
          <xsl:value-of select="java:xml.XPointer.getXPointer(.)"/>
        </xsl:attribute>

        <xsl:attribute name="target">
          <xsl:value-of select="generate-id()"/>
          <xsl:text>tag1</xsl:text>
        </xsl:attribute>
      </reference>

      <xsl:apply-templates select="*" mode="reference"/>
    </xsl:template>
  

The attribute source is generated via a call to the method getXPointer(NodeList nodeList) of of the class xml.XPointer. This class is shipped with TAXI and contained by the jar taxi.jar located in lib. This method accepts a NodeList as parameter which is actually the context node in the stylesheet. The context node is a node of the XML source document catched by the template. The method getXPointer(NodeList nodeList) generates the XPointer to go to that node from the root of the XML source document.

To generate the attribute target, you do whatever you want. This attribute must be the value of an existing box's id. In this stylesheet, we generate this value that way :

    <xsl:attribute name="target">
      <xsl:value-of select="generate-id()"/>
      <xsl:text>tag1</xsl:text>
    </xsl:attribute>
  

When generating the structure of boxes, a box's id has been generated the same way (lines 39-42 of the stylesheet) :

    <xsl:template match="*" mode="box">
      <hbox>
        <xsl:attribute name="id">
          <xsl:value-of select="generate-id()"/>
          <xsl:text>tag1</xsl:text>
        </xsl:attribute>

        ...

      </hbox>
    </xsl:template>