Xslt Exercise
Gw
The goal of this exercise is to make yourself familiar with XSLT,
which many of you will be using heavily in the GW project. We give you
a few sample exercises, but encourage you to try out what happens if
you change the input or the required presentation.
For XSLT resources, see the
technical documentation for GW. Just
pick one of the tutorials, depending on how much you already know
about XML and XSLT. The XPath service listed in the XPath section is
very useful to learn how to use XPath.
If this is your first time on a Linux machine at the UU, then you
might find the tips in
user friendly linux useful to read first.
Applying an XSL Transformation
First, let's make sure that you know how to apply an XSL
transformation. You can do this in many different ways, but for now
xsltproc (part of libxslt) and your browser (Firefox/Mozilla/IE6)
are the most convenient ways. Usually, error reporting is somewhat
better at the command-line, so we advice you to use
xsltproc.
Using xsltproc
Input: hello.xml
<?xml version="1.0"?>
<hello>World</hello>
Transformation: world.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="hello">
<html>
<head>
<title>Hello <xsl:value-of select="."/></title>
</head>
<body>
<h1>Hello <xsl:value-of select="."/></h1>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Apply xsltproc:
$ xsltproc world.xsl hello.xml
You can save the output in a file to view it in your browser:
$ xsltproc world.xsl hello.xml > hello.html
Using XSLT in a Browser
For your browser, you can add processing instruction that tells the
browser to apply a stylesheet to the XML file.
Input: hello-browser.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="world.xsl"?>
<hello>World</hello>
This should show a somewhat big
Hello World message if you open this
xml file.
A Simple XSL Transformation
In this exercise, we will style information about a Subversion
repository to HTML. First of all, checkout the data of the GW wiki of
last year using the command:
$ svn checkout https://svn.cs.uu.nl:12443/repos/test-wiki/
and go to the directory test-wiki. You will see all kinds of files
here, which are part of the data of the wiki of last year. For
example, the file
WonderLand tells you a nice story about a young
girl.
Now, suppose that we want know what has been going on this wiki. We
can request the log to see who has committed what, when, and why.
$ svn log --verbose
This information is very useful, but hard to process for a computer
program. Therefore, the Subversion developers have implemented support
for getting the log in an XML format.
$ svn log --xml --verbose
Of course this is horrible to read, but for a computer program this is
perfect, since there are a lot of standard languages and libraries to
process XML files. We will process this XML format to a nice HTML file
in the next exercise, but you will first implement a small XSLT
stylesheet. You could skip to the next exercise if you already know
the basics of XSLT.
First, modify one of the files. For example, give your personal touch
to the Alice in Wonderland story. You've now changed one of the files
in the Subversion checkout, and one of the operations a version
management system has to support is to give you information about what
you've been doing in a checkout. You can do this with the command:
$ svn status
You can get more information about
all the files by adding the
--verbose option to the command:
$ svn status --verbose.
This information is very useful, for you, as well as for computer
programs. Unfortunately, the Subversion developers have not yet
implemented an XML option for the
svn status command.
For example, the following format could be used for that:
<?xml version="1.0"?>
<status>
<file path="Wonderland">
<changes>
<modified/>
</changes>
<working-revision>12766</working-revision>
<last-committed>
<revision>12734</revision>
<author>that's you</author>
</last-committed>
</file>
<file path="trunk/WebLeftBar">
<changes/>
<working-revision>12766</working-revision>
<last-committed>
<revision>12734</revision>
<author>mbravenboer</author>
</last-committed>
</file>
<file path="trunk/WebHome">
<changes>
<added/>
</changes>
<working-revision>12766</working-revision>
<last-committed>
<revision>1234</revision>
<author>visser</author>
</last-committed>
</file>
</status>
Now, implement an XSL Transformation that transforms this format to a
simple HTML table. For example, produce the following output for the
given input:
<html>
<head>
<title>Subversion Status</title>
</head>
<body>
<table cellspacing="10">
<tr>
<th>Path</th>
<th>Changes</th>
<th>Working Revision</th>
<th>Last Committed Revision</th>
<th>Last Committed Author</th>
</tr>
<tr>
<td>Wonderland</td>
<td>A</td>
<td>12766</td>
<td>12734</td>
<td>that's you</td>
</tr>
<tr>
<td>trunk/WebLeftBar</td>
<td/>
<td>12766</td>
<td>12734</td>
<td>mbravenboer</td>
</tr>
<tr>
<td>trunk/WebHome</td>
<td>A</td>
<td>12766</td>
<td>1234</td>
<td>visser</td>
</tr>
</table>
</body>
</html>
More Complete XSL Transformations
Let's now try to do something more interesting, useful, and fancy. The
svn log commands gives us a lot of information. Let's try to
transform that to an attractive HTML page. The goal is to produce
something that looks like this:
Don't worry: we give you a CSS stylesheet and images. They are
available here:
Download the tarball, and use
tar zxvf svnlog.tar.gz to extract the files.
Next, dump the XML log to a file:
$ svn log --xml --verbose > svnlog.xml
To help you a bit, we give you HTML skeletons for the different parts
of the Subversion log. The skeleton of the resulting HTML file should
be something like:
<html>
<head>
<title>Subversion Log</title>
<link rel="stylesheet" type="text/css" href="svnlog.css"/>
</head>
<body>
....
</body>
</html>
The skeleton of a logentry:
<div class="logentry">
<p>
<a name="1111"/>
<img src="page_number_24.gif" align="middle"/>
<a href="#1111" title="Link to this commit">1111</a>
<img src="calendar_24.gif" align="middle" style="margin-left: 15pt"/>
2005-01-03 15:24
<img src="user_24.gif" align="middle" style="margin-left: 15pt"/>
username
</p>
<div class="commitmsg">
<pre width="85">
<code>
...
</code>
</pre>
</div>
<table border="0" cellspacing="5">
... paths ...
</table>
</div>
For every path in the logentry, there should be a table row in the
table of the previous skeleton. In the next skeleton for a path,
path,
previousrevision, and
thisrevision should be replaced by
their actual values.
<tr>
<td>
<img src="edit_16.gif" title="Modified"/>
or
<img src="plus_16.gif" title="Added"/>
or
<img src="delete_16.gif" title="Deleted"/>
</td>
<td>path</td>
<td>
<a href="https://svn.cs.uu.nl:12443/repos/test-wiki/path" title="Open file">
<img border="0" src="open_16.gif"/>
</a>
</td>
<td>
<a href="https://svn.cs.uu.nl:12443/viewcvs/test-wiki/path" title="Open file in ViewCVS">
<img border="0" src="zoom_16.gif"/>
</a>
</td>
<td>
if this path was modified:
<a
href="https://svn.cs.uu.nl:12443/viewcvs/test-wiki/path?r1=previousrevision&r2=thisrevision&p1=path&p2=path"
title="View difference to previous revision in ViewCVS">
<img border="0" src="window_tile_vert_16.gif"/>
</a>
</td>
</tr>
One of the tricky parts is the transformation of the date. The problem
with the date in the XML input is that is not represented in XML and
therefore it is difficult to process. We give you the XSLT code for
that, but you will improve this code in the next exercise:
<xsl:value-of select="substring(date/text(), 1, 4)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring(date/text(), 6, 2)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring(date/text(), 9, 2)"/>
<xsl:text> </xsl:text>
<xsl:value-of select="substring(date/text(), 12, 2)"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="substring(date/text(), 15, 2)"/>
Another tricky part is the link to the viewcvs page. You need the
previous revision number for that. You can do this with the axis
ancestor. Ask your neighbor, or skip this if you really cannot find
out how this works.
Tip: it is good style to use recursive calls to separate templates and
not explicit control-flow, using for example
for-each. Try to use
separate templates for the modified, added, and deleted images. For
this, you have to make a template that matches these specific actions.
Using the EXSLT extensions
Of course, the code for the representation of a date is horrible. The
type of this date format is one of the XML Schema data
types. Fortunately, XSLT is an extensible language and the community
has standardized a useful set of XSLT extensions. One of these
extensions is the handling of dates and times.
To use this extension for dates and times, you have to add the
following declarations to the
xsl:stylesheet element:
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date">
You can now use the functions define in the
date namespace. They are
explained here:
Example:
<xsl:value-of select="date:year(date/text())"/>
Now change your stylesheet to format the date using these functions
(
year,
month-in-year, etc).