Home Books Software Projects Forums

XSLT by Example

Writing XPath expressions and using variables.

Table of Contents

What is XPath?

XML Path Language (XPath) is a companion specification to the XSLT specification. The purpose of XPath is to provide a notation for accessing parts of an XML document.

An XML document may be modeled as a tree of nodes. The different types of nodes found in the tree include element nodes, attribute nodes and text nodes. An XPath expression is used to find these nodes during the XSLT transformation process.

How do you find all instances of an element in a document?

We need to find all of the Class and Interface definitions in an XMI document. However, since the XMI specification allows these elements to appear at various different points in the document hierarchy, the challenge is to find them wherever they appear. We accomplish this by using the following XPath expression in an xsl:apply-templates instruction:

<!-- Classes -->
<xsl:apply-templates select="//Foundation.Core.Class[@xmi.id]">

The XPath notation '//' instructs the processor to search for Class elements beginning from the root of the document and then continuing on through each level of the node tree. This notation is actually an abbreviation for a longer 'axis specifier' defined by the XPath standard; however, since this notation is so convenient, it is almost always used in place of the longer notation.

How do you limit your results to only elements that contain a specific attribute?

XPath expressions may contain a 'predicate', which is a qualifying expression that serves to constrain the result-set returned.

In our example, an XMI document may contain both 'definitions' and 'references' to Class elements. Class definitions are identified by containing an xmi.id attribute, whereas references to Class definitions are identified by containing an xmi.idref attribute. When creating the HTML for classes we use the notation for a predicate, '[ ]', to select only elements which have the xmi.id attribute because we want the class definitions.

<!-- Classes -->
<xsl:apply-templates select="//Foundation.Core.Class[@xmi.id]">

The '@' symbol identifies an attribute. So the way we read this full expression is as follows: Beginning from the root, find all Class elements in the document that contain the xmi.id attribute.

Note that the '@' symbol is another abbreviation for an axis specifier. In this case the abbreviation is for the 'attribute axis'.

How do you get the value of an element?

The whole goal of XSLT is to transform elements from a source XML document into elements of a different form in the result document, in our case an XHTML document. Once we've found the element we want through the use of an XPath expression, the way to get its value is by means of an xsl:value-of instruction. The following code is used to format the name given to a model into an XHTML <title> for our resulting page:

<!-- Window Title -->
<xsl:template match="Model_Management.Model" mode="head">
    <title>
	<!-- Name of the model -->
        <xsl:value-of select="Foundation.Core.ModelElement.name"/>
    </title>
</xsl:template>

When this template is invoked, the current context is the Model_Management.Model element. The name of the model is a child-node of this model element. We extract the name using the xsl:value-of instruction and enclose it inside its new XHTML <title> tag. The XPath expression to extract the name is 'Foundation.Core.ModelElement.name' and appears as the value of the 'select' attribute in the xsl:value-of instruction.

How do you get the value of an attribute?

Besides the name of an element, the next most common feature of an element that our stylesheet is frequently found accessing is the xmi.id attribute, which is used in XMI documents as a unique identifier for an element in a UML model. As you may recall from above, the '@' symbol is the abbreviated notation for referencing an attribute. Thus we use the following code to extract the value of an xmi.id and assign it to a variable:

<xsl:variable name="xmi_id" select="@xmi.id" />
What are variables?

XSLT variables are similar to variables in other programming languages with the major exception that they may only be assigned a value once, at the time they are declared. This may sound odd, at least until the purpose of XSLT variables is understood.

The chief purposes for which we use variables in our stylesheet are to aid in readability and to avoid repeating lengthy XPath expressions. This is accomplished by declaring variables using the xsl:variable instruction and assigning them XPath expressions as values. The variable is then used in other XSLT instructions in place of using a full XPath expression. When a variable is used, it is prefixed with the '$' symbol to distinguish it from regular XPath expressions.

The following code is taken from the xsl:template which finds the supertypes for a class:

<!-- Supertypes (inheritance) -->
<xsl:template name="supertypes">
    
    <!-- Generalizations identify supertypes -->
    <xsl:variable name="generalizations" 
         select="Foundation.Core.GeneralizableElement.generalization/
                 Foundation.Core.Generalization"/>

Here we see the declaration of an xsl:variable with the name "generalizations". It is assigned a value through the select attribute, which contains an XPath expression that finds generalization relationships within the current context of the XMI document (a class or interface).

This variable is used twice within the template. The first time it is used in conjunction with the count() function to determine if any supertypes exist for the class or interface.

<xsl:if test="count($generalizations) > 0">

If generalizations are found, we proceed to output the list of names using the xsl:for-each instruction. This is the second time we use the variable, here to produce the node list for the iteration:

<xsl:for-each select="$generalizations">

As you can see, the use of variables aids significantly in creating more concise, readable code.




Valid XHTML 1.0!