Login | Register
My pages Projects Community openCollabNet

XSLT Evaluation

Overview

XSLT uses XML as input and can output both XML and non-XML. Templates are matched against XML elements in the input that are selected using XPath expressions. It's moslty declarative as opposed to the other languages that are imperative and it does not require direct interaction with the inner-works of the models, the author works just with XML data. In order for a tool to be used with ArgoPrint/XSLT an XML representation of the data must be available.

Resources:

Conditionals

<xsl:if test="expr">

</xsl:if>

evaluates expr and if the value evaluates to boolean true or to an non-empty string than the content of the element is evaluated.

<xsl:choose>
 <xsl:when test="expr1">
 </xsl:when>
 <xsl:when test="expr2">
 </xsl:when>
 ...
 <xsl:otherwise>
 </xsl:otherwise>
</xsl:choose>

Is equivalent to a case statement and can be used to implement if-then-else constructs.

Iteration

<xsl:foreach select="expr">
 ...
</xsl:foreach>

For all elements that match the select expression the content of the element is exaluated.

Sorting

<xsl:apply-templates select="...">
 <xsl:sort select="...">
 ...
</xsl:apply-templates>

or

<xsl:for-each select="...">
 <xsl:sort select="...">
 ...
</xsl:for-each>

The sort element must be a child of for-each or apply-templates. The order (ascending/descending), comparison type (as string/as number) and the case order (uppercase first/lower case first) can be specified.

Multiple data sources

Combination of multiple XML sources can be done by using the document() function that takes as an argument the XML's filename. In order to specify elements in the other XML files besides the input, XPath expressions are prefixed with document(fileName).

Tools

A list with XSLT tools is available at http://www.xslt.com/resources.html most of them are non-free. Xalan-J is a free implementation from Apache released under Apache License 2.0.

Code

  • Shows a subset of classes based on the name of the containing package in chapter 1.
  • For each of these classes, shows all the names and types of the attributes. For those classes that doesn't have attributes include instead the text "No attributes."
    <xsl:stylesheet
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
         version="1.0">
      <xsl:output method="html"/>
    
    <xsl:template match="/">
     <html><head><title>Test</title></head><body>
      <xsl:apply-templates select="argouml"/>
     </body></html>
    </xsl:template>
    
    <xsl:template match="argouml/package">
     <xsl:variable name="current" select="@name"/>
    
     <h2>Package <xsl:value-of select="@name"/></h2>
     <xsl:for-each select="/argouml/class[@package=$current]">
      <h3>Class <xsl:value-of select="@name"/></h3>
      <ul>
      <xsl:choose>
       <xsl:when test="attr">
        <xsl:for-each select="attr">
    	<li>
    	 <xsl:value-of select="@name"/>:
    	 <xsl:value-of select="@type"/>
    	</li>
        </xsl:for-each>
       </xsl:when>
       <xsl:otherwise>
    	<li>No attributes</li>
       </xsl:otherwise>
      </xsl:choose>
      </ul>
     </xsl:for-each>
    </xsl:template>
    
    </xsl:stylesheet>
    
  • Shows a subset of classes based on the name of one of the stereotypes in chapter 2.
  • For each of these classes, shows the signature of all the operations including return value, direction, name, and type of each parameter. Each method as a bullet in a bulleted list.
    <xsl:template match="argouml/stereotype">
     <xsl:variable name="current" select="@name"/>
    
     <h2>Stereotype <xsl:value-of select="@name"/></h2>
     <xsl:for-each select="/argouml/class[stereotype/@name=$current]">
      <h3>Class <xsl:value-of select="@name"/></h3>
      <ul>
      <xsl:choose>
       <xsl:when test="operation">
        <xsl:for-each select="operation">
    	<li>
    	 <xsl:value-of select="@name"/>
    	 <xsl:if test="@return_type|@return_type!='void'">
    		:<xsl:value-of select="@return_type"/>
    	 </xsl:if>
    	 <ul>
    	 <xsl:for-each select="parameter">
    	  <li>
    	   <xsl:value-of select="@name"/>:
    	   <xsl:value-of select="@type"/>
    	  </li>
    	 </xsl:for-each>
    	 </ul>
    	</li>
        </xsl:for-each>
       </xsl:when>
       <xsl:otherwise>
    	<li>No operation.</li>
       </xsl:otherwise>
      </xsl:choose>
      </ul>
     </xsl:for-each>
    </xsl:template>
    
  • Show a subset of classes based on the existance of a parameter named "something" in any of the operations in the class in chapter 3.
  • For each of these classes, if they contain operations other than the one named "something", show these in a table with one operation on each line with the operation name in the first column and then one column per distinct type for all parameters with the names of the parameters filled in the table. For those classes that doesn't have any other operations, include instead the text "No other operations."
    <xsl:template match="argouml/class">
     <xsl:if test="operation[parameter/@name='something']">
      <h2>Class <xsl:value-of select="@name" /> </h2>
    
       <xsl:comment>test if other operations exist</xsl:comment>
       <xsl:if test="operation[parameter/@name!='something']">
        <xsl:comment>
         creates a list of parameters with unique type
        </xsl:comment>
        <xsl:variable
         name="uniqueTypes"
         select="operation[not(parameter/@name='something')]
    /parameter[not(@type=../preceding::operation[not(parameter/@name='something')]
    /parameter/@type
    or
    @type=preceding-sibling::parameter/@type)]" />
    
        <table border="1">
         <xsl:comment>
            creates the header by iterating on that list
         </xsl:comment>
          <tr>
           <td>Operation</td>
    
            <xsl:for-each select="$uniqueTypes">
             <td><xsl:value-of select="@type" /></td>
            </xsl:for-each>
          </tr>
    
         <xsl:comment>
            for each operation start a new row and for each unique type iterate through the parameter list of the method and add the
    name of the parameter to the cell of the current unique type
         </xsl:comment>
    
         <xsl:for-each select="operation[parameter/@name!='something']">
          <xsl:variable name="currentOperation" select="." />
           <tr>
            <td>
             <xsl:value-of select="$currentOperation/@name" />
            </td>
            <xsl:for-each select="$uniqueTypes">
             <xsl:variable name="currentType" select="@type" />
              <td>
               <xsl:for-each select="$currentOperation/parameter[@type=$currentType]">
                <xsl:text> </xsl:text>
                 <xsl:value-of select="@name" />
                </xsl:for-each>
              </td>
    
            </xsl:for-each>
           </tr>
         </xsl:for-each>
        </table>
       </xsl:if>
      </xsl:if>
    </xsl:template>
    
  • Show all use case diagrams in chapter 4
  • Under each use case diagram, a list of actors and a list of use cases both with their explanations.
    <xsl:template match="argouml/ucdiagram">
     <xsl:element name="img">
      <xsl:attribute name="src"><xsl:value-of select="concat(@name,'.png')"/></xsl:attribute>
      <xsl:attribute name="alt"><xsl:value-of select="concat('Diagram ', @name)"/></xsl:attribute>
     </xsl:element>
     <h3>Actors:</h3>
     <ul>
     <xsl:for-each select="actor">
      <li>
      <xsl:value-of select="@name"/>
      <xsl:value-of select="@explenation"/>
      </li>
     </xsl:for-each>
     </ul>
     <h3>Usecases:</h3>
     <ul>
     <xsl:for-each select="usecase">
      <li>
      <xsl:value-of select="@name"/>
      <xsl:value-of select="@explenation"/>
      </li>
     </xsl:for-each>
     </ul>
    </xsl:template>
    
  • Show the use cases that are linked to a requirement (requirements fetched from some other tool than argouml indexed on the use case names) in chapter 5.
  • Under each use case, show the requirement text.
    <xsl:template match="argouml/ucdiagram">
     <h2>
       <xsl:text>Usecase Diagram </xsl:text>
       <xsl:value-of select="@name"/>
     </h2>
     <ul>
     <xsl:for-each select="usecase">
      <li>
      <xsl:variable name="current" select="@name"/>
      <xsl:if test="document($reqtool)/requirements/requirement[@name=$current]">
        <xsl:value-of select="$current" />
        <xsl:text> requirement:</xsl:text>
        <xsl:value-of select="document($reqtool)/requirements/requirement[@name=$current]/@text"/>
      </xsl:if>
      </li>
     </xsl:for-each>
     </ul>
    </xsl:template>
    
  • Create a template that creates a html site with two frames. One tree on the left with all actors, use cases, classes, attributes, operations, and then one page per actor, class, use case.

    Note:The code combinining the two frames is static.

    <xsl:template match="argouml">
     <h2>Actors</h2>
     <ul>
     <xsl:for-each select="ucdiagram/actor">
      <li>
       <xsl:variable name="filename" select="concat('actor_',@name,'.html')"/>
       <xsl:element name="a">
        <xsl:attribute name="href">
         <xsl:value-of select="$filename" />
        </xsl:attribute>
        @name
       </xsl:element>
       <redirect:write select="$filename">
        <xsl:comment>Write the details of each actor</xsl:comment>
       </redirect:write>
      </li>
     </xsl:for-each>
     </ul>
    
     <xsl:for-each select="ucdiagram/usecase"> 
      <xsl:comment>similar to above</xsl:comment>
     </xsl:for-each>
    
     <xsl:for-each select="class">
      <xsl:comment>similar to above</xsl:comment>
     </xsl:for-each>
    
    </xsl:template>
    

Notes

  • Length - easy to learn, only the XPath specifications differ for various sources
  • Complexity - simple rules for XPath, declarative language
  • Error prone - ?
  • Error spoting - ?