6. Iteration

Next, we are going to add an HTML list that displays all the available metadata about the letters that are described in the source file. These letters can all be found within the <body> element, underneath <collection>. Each letter is described in a separate <letter> element. These <letter> elements contain information about the sender, the recipient, the place and date of crreation and the langauge.

To display some of the metadata about the letters, we could make the following stylesheet.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

<xsl:template match="collection">

        <html>
              <head><title>XSLT Transformation</title>
         </head>

       <body>
              <p>

                
                <ul>

                <li>
                <b>From
                  <xsl:value-of select="body/letter/author"/>
                    to <xsl:value-of select="body/letter/recipient"/>
                </b>

                <br/>
                <xsl:value-of select="body/letter/place"/> <br/>
                <xsl:value-of select="body/letter/year"/> <br/>
                <xsl:value-of select="body/letter/callnumber"/>
                </li>

                </ul>
              
                </p>
            </body>
        </html>
</xsl:template>

</xsl:stylesheet>
  

In this example, we want to be able to select specific elements within <body>, such as the name of the author of a letter and the date of the letter. These elements are not in the direct context, however. As was explained earlier, the 'context' consists of the element mentioned in the @value attibute of <template>, and its direct children. In our sample file, the context is set to <collection>, <head> and <body> in this first template. If we want to refer to elements outside of the direct context, we need to formulate a path towards these elements. To select the author of a letter, for example, we need to work with the expression body/letter/author

In stylesheets, the XSLT elements can be combined quite easily with HTML tags. In the stylesheet above, the name of the author and the recipient, for instance, are given in bold.

If the file collection.xml is transformed using the stylesheet that was discussed provided, the result will look as follows in an internet browser:

As you can see, only one letter is shown, whereas the XML file actually describes a collection of letters. The <xsl:value-of> element can be used to select the contents of specific elements, but when there are multiple elements with the same name on the same hierarchical level, only the first element will be selected.

If all the elements on this level need to be shown, the element <xsl:for-each> will provide a solution. This element has a select attribute which refers to the element that occurs more than once on a certain level in the tree. The instructions which must be performed for each element must be included in between the opening and closing tag of the <xsl:for-each> element. The situation can be visualised as follows:

Note that there are some important difference between the <xsl:value-of> element and the <xsl:for-each> element. A first difference is that <xsl:value-of> is an empty element. It is an element without any contents and without andy subelements. In the case of <xsl:for-each>, on the other hand, there are typically a number of elements and subelements in between its opening and the closing tags.

A second important difference is that <xsl:for-each> changes the context. The paths within the opening and closing tags of <xsl:for-each> no longer depart from <collection>, but from <letter>, which is the element which is mentioned in the select attribute of the <xsl:for-each> element. Within <xsl:for-each>, <xsl:value-of select="author"> thus needs to be used instead of <xsl:value-of select="body/letter/author"/>.

As you can see, the HTML <li> element is within the body of the <for-each> element. The stylesheet needs to produce a bullet for each letter in the collection. The HTML <ulo> element is OUTSIDE of the body of the <for-each> element. This <ulo> element needs to be added only once.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

<xsl:template match="collection">

    <html>
    <head></head>

    <body>
    <p>
    <ul>

    <xsl:for-each select="body/letter">
    <li>

        
    <b>From <xsl:value-of select="author"/>
    to <xsl:value-of select="recipient"/>

    </b><br/><xsl:value-of select="place"/>

    <br/><xsl:value-of select="year"/><br/>

    <xsl:value-of select="callnumber"/>


    </li>
    </xsl:for-each>
    </ul>
    </p>
    </body>
    </html>

</xsl:template>

</xsl:stylesheet>

If the XML source, collection.xml, is tranformed using stylesheet above, all the letters will fortunately be shown.

Make exercise 4