This example includes the XSLT file used in the XSLT Document Map.
The example demonstrates using the key() function and <xsl:key> element to group data into categories.
The mode attribute is used to produce two different tables from the same XML data. For more information about modes, see xsl:apply-templates Element.
Use the Sample XML File (books.xml). Below the line <?xml version='1.0'?>, add the following line:
<?xml-stylesheet type="text/xsl" href="books.xsl"?>
The books.xsl file loads the following XML file to demonstrate the document() function:
<?xml version='1.0'?> <document> <watermark>Scootney Publishing</watermark> <copyright>Copyright 2000, Scootney Publishing. All Rights Reserved.</copyright> </document>
This file is the same one that is shown in the document map. It provides examples of common tagging within an XSLT file.
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:variable name="recentdate">2001-01-01</xsl:variable>
<xsl:variable name="ancillary" select="document('ancillary.xml')"/>
<xsl:key name="categ_key" match="book" use="genre"/>
<xsl:key name="author_key" match="book" use="author"/>
<xsl:template match="/">
<html>
<head>
<title>Scootney Publishing: Special Exhibit</title>
<style>
h1 {font-family: Arial,Helvetica,Univers,sans-serif;
font-size: 18pt; background-color: #00CCCC; width: 90%}
h2 {font-family: Arial,Helvetica,Univers,sans-serif;
font-size: 14pt; width: 90%}
h3 {font-family: Arial,Helvetica,Univers,sans-serif;
font-size: 12pt; background-color: gold;
width: 90%; border-width: 1; border-style: solid}
h4 {font-family: Arial,Helvetica,Univers,sans-serif;
font-size: 11pt; background-color: gold;
width: 33%; border-width: 1; border-style: solid}
</style>
</head>
<body>
<div style="position:absolute;font-size:96;
font-family:Times New Roman;color:#F0F0F0;z-index:-1">
<xsl:value-of select="$ancillary//watermark"/>
</div>
<h1> Scootney Publishing: Special Exhibit Catalog</h1>
<!-- Group by catalog in first pass, then by author. -->
<xsl:apply-templates select="catalog" mode="grp_categ"/>
<xsl:apply-templates select="catalog" mode="grp_author"/>
<p/>
<div style="font-size:9">
<xsl:value-of select="$ancillary//copyright"/>
</div>
</body>
</html>
</xsl:template>
<xsl:template match="catalog" mode="grp_categ">
<h2>Titles Grouped by Genre</h2>
<xsl:for-each select="book[count(. | key('categ_key', genre)[1])=1]">
<h3> <xsl:value-of select="genre"/></h3>
<xsl:for-each select="key('categ_key', genre)">
<xsl:sort select="title"/>
<table border="0" width="75%">
<tr>
<th width="10%" align="right">Title</th>
<td width="90%" align="left"><xsl:value-of select="title"/></td>
</tr>
<tr>
<th width="10%" align="right">Author</th>
<td width="90%" align="left"><xsl:value-of select="author"/></td>
</tr>
<tr>
<th width="10%" align="right">Copyright</th>
<td width="90%" align="left">
<xsl:value-of select="publish_date"/>
<xsl:if test="substring(publish_date,1,4) >= substring($recentdate,1,4)">
  <b>new</b>
</xsl:if>
</td>
</tr>
<tr>
<th width="10%" align="right">Price</th>
<td width="90%" align="left"><xsl:value-of select="price"/></td>
</tr>
<tr>
<th width="10%" align="right" valign="top">Summary</th>
<td width="90%" align="left"><xsl:value-of select="description"/></td>
</tr>
</table>
<hr width="75%" align="left"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="catalog" mode="grp_author">
<h2>Titles Grouped by Author</h2>
<xsl:for-each select="book[generate-id() = generate-id(key('author_key', author)[1])]">
<xsl:sort select="author"/>
<h4> <xsl:value-of select="author"/></h4>
<xsl:for-each select="key('author_key', author)">
<xsl:sort select="title"/>
 <xsl:value-of select="title"/><br/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
You can view the output in Microsoft® Internet Explorer.
Document Map (XML Developer's Guide) | Grouping Data by Examining the Keyed Node-set