CSCI E-153, Web Development Using XML

XML

September 7, 2010

Harvard University
Division of Continuing Education
Extension School

Course Web Site: http://cscie153.dce.harvard.edu/

Instructor email: david_heitmeyer@harvard.edu
Course staff email: cscie153@dce.harvard.edu

Well-formed XML Documents

Nodes

Nodes (computer science)
From Wikipedia, the free encyclopedia

A node is an abstract basic unit used to build linked data structures such as trees, linked lists, and computer-based representations of graphs. Each node contains some data and possibly links to other nodes.

A node can be thought of as a logical placeholder for some data. By forming chains of interlinked nodes, very large and complex data structures can be formed.

tree

A Tree

<addressbook>
  <contact>
    <name>David Heitmeyer</name>
    <address>8 Story Street</address>
    <city>Cambridge</city>
    <state>Massachusetts</state>
    <zip>02138</zip>
    <phone type="office">617-999-5870</phone>
    <email>david_heitmeyer@harvard.edu</email>
  </contact>
  <contact>
    <name>Drew Gilpin Faust</name>
    <address>Massachusetts Hall</address>
    <city>Cambridge</city>
    <state>Massachusetts</state>
    <zip>02138</zip>
    <email>president@harvard.edu</email>
  </contact>
</addressbook>

tree

nodes

Mechanics of an XML Document

XML Declaration

<?xml version="1.0" encoding="UTF-8" ?>

XML version

1.0
Extensible Markup Language (XML) 1.0 (Fifth Edition), November 2008

XML encoding

XML supports Unicode

You may also see ISO-8859-1 quite a bit (also known as Latin-1). When in doubt, use UTF-8 (it is the default anyway).

Suggested reading on Unicode: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Character Entities

In XML, there are only 5 named character entities defined:

Numeric Character Entities

Use &#nnn; (nnn = decimal number) or &#xnnnn; (nnnn = hexadecimal number).

Named Entities from XHTML

Named entities (e.g. &copy;) are defined as part of the markup language.
Named XHTML entities are not available generally in XML documents.

XML document mechanics and meaning

What is the Difference?

  1. <message>
      <greeting>
      <![CDATA[
        

    Hello Kitty! from Sanrio

    ]]> </greeting> </message>
  2. <message>
      <greeting>
        &lt;p&gt;&lt;strong>Hello Kitty!&lt;/strong&gt; from
        &lt;a href="http://www.sanrio.com/"&gt;Sanrio&lt;/a&gt;
        &lt;/p&gt;
      </greeting>
    </message>
      
  3. <message>
      <greeting>
        <p><strong>Hello Kitty!</strong> from
        <a href="http://www.sanrio.com/">Sanrio</a>
        </p>
      </greeting>
    </message>
      

nodes


nodes

XHTML and MathML

mathml screenshot

mathml

XML Namespaces

XHTML and MathML

Define prefix and namespace URI binding and default namespace:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:mml="http://www.w3.org/1998/Math/MathML">

Use MathML inline in XHTML document:

<p>In order to mix XHTML and MathML, we need to include the proper DTD and also pay attention to XML namespaces!</p>
<mml:math>
  <mml:mtext>The roots of the quadratic equation</mml:mtext>
  <mml:mspace width="2em"/>
  <mml:mi>a</mml:mi>
  <mml:mo>&InvisibleTimes;</mml:mo>
  <mml:msup>
  <!-- content removed for clarity -->

XML Namespaces

mathml

Parts

Purposes

Setting Default Namespaces

The following documents have the same "meaning":

Snippet XHTML and MathML, with "mml" prefix used for all "MathML" elements.

<html xmlns="http://www.w3.org/1999/xhtml" 
  xmlns:mml="http://www.w3.org/1998/Math/MathML">  
  <head>
    <title>XHTML and MathML Example</title>
  </head>
  <body>
    <h1>XHTML and MathML Example</h1>
      <p>In order to mix XHTML and MathML, we need to include 
      the proper DTD and also pay attention to XML namespaces!</p>
      <mml:math>
        <mml:mtext>The roots of the quadratic equation</mml:mtext>
        <mml:mspace width="2em"/>
        <mml:mi>a</mml:mi>
        <mml:mo>&InvisibleTimes;</mml:mo>
        <mml:msup>
          <mml:mi>x</mml:mi>
          <mml:mn>2</mml:mn>
        </mml:msup>
        <mml:mo>+</mml:mo>
        <mml:mi>b</mml:mi>
        <mml:mo>&InvisibleTimes;</mml:mo>
        <mml:mi>x</mml:mi>
        <mml:mo>+</mml:mo>
        <mml:mi>c</mml:mi>
        <mml:mo>=</mml:mo>
        <mml:mn>0</mml:mn>
        <!-- truncated for space reasons ... -->
  

XHTML and MathML, with MathML defined as default namespace for "math" element and all children.

<html xmlns="http://www.w3.org/1999/xhtml">
  
  <head>
    <title>XHTML and MathML Example</title>
  </head>
  <body>
  <h1>XHTML and MathML Example</h1>
  <p>In order to mix XHTML and MathML, we need to include 
  the proper DTD and also pay attention to XML namespaces!</p>
  <math xmlns="http://www.w3.org/1998/Math/MathML">
    <mtext>The roots of the quadratic equation</mtext>
    <mspace width="2em"/>
    <mi>a</mi>
    <mo>&InvisibleTimes;</mo>
    <msup>
      <mi>x</mi>
      <mn>2</mn>
    </msup>
    <mo>+</mo>
    <mi>b</mi>
    <mo>&InvisibleTimes;</mo>
    <mi>x</mi>
    <mo>+</mo>
    <mi>c</mi>
    <mo>=</mo>
    <mn>0</mn>
    <!-- truncated for space reasons-->

XML Namespaces: Prefix and URI

Need to bind a prefix to a URI.

W3C RSS document

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:hr="http://www.w3.org/2000/08/w3c-synd/#"
         xmlns:h="http://www.w3.org/1999/xhtml"
         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xmlns="http://purl.org/rss/1.0/">

GovTrack.US People RDF Data

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:usgov="tag:govshare.info,2005:rdf/usgovt/"
	xmlns:bill="tag:govshare.info,2005:rdf/usbill/"
	xmlns:vote="tag:govshare.info,2005:rdf/vote/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:dcterms="http://purl.org/dc/terms/"
	xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"
	xmlns:pol="tag:govshare.info,2005:rdf/politico/"
	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:time="http://pervasive.semanticweb.org/ont/2004/06/time#">

Extensible Stylesheet Language Transformations (XSLT) and XML Path Language (XPath)

XSLT

XPath

Simple XSLT Example as an Introduction

XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>
          <xsl:value-of select="/rss/channel/title"/>
        </title>
      </head>
      <body>
        <xsl:apply-templates select="/rss/channel/item/">
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="item">
    <p>
      <a href="{link}">
        <xsl:value-of select="title"/>
      </a>
      <br/>
      <xsl:value-of select="description"/>
    </p>
  </xsl:template>
  
  <xsl:template match="text()"/>
  
</xsl:stylesheet>

XSLT Processors at work

XSLT Processor


A closer look:

XSLT Processor

XSLT Processors

In this course we will be using the XSLT processors Saxon (Michael Kay) and Apache Xalan (Apache Software Foundation).

XSLT Examples

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">  
  <channel> 
    <title>BBC News - World</title>  
    <link>http://www.bbc.co.uk/go/rss/int/news/-/news/world/</link>  
    <description>The latest stories from the World section of the BBC News web site.</description>  
    <language>en-gb</language>  
    <lastBuildDate>Tue, 31 Aug 2010 17:19:47 GMT</lastBuildDate>  
    <copyright>Copyright: (C) British Broadcasting Corporation, see http://news.bbc.co.uk/2/hi/help/rss/4498287.stm for terms and conditions of reuse.</copyright>  
    <docs>http://www.bbc.co.uk/syndication/</docs>  
    <ttl>15</ttl>  
    <atom:link href="http://feeds.bbci.co.uk/news/world/rss.xml" rel="self" type="application/rss+xml"/>  
    <item> 
      <title>Iraq PM hails US troop withdrawal</title>  
      <description>Iraq's prime minister says the country is now "independent", hours before US combat operations are due to end officially.</description>  
      <link>http://www.bbc.co.uk/go/rss/int/news/-/news/world-middle-east-11137269</link>  
      <guid isPermaLink="false">http://www.bbc.co.uk/news/world-middle-east-11137269</guid>  
      <pubDate>Tue, 31 Aug 2010 17:49:17 GMT</pubDate>  
      <media:thumbnail width="66" height="49" url="http://news.bbcimg.co.uk/media/images/48929000/jpg/_48929269_010076484-1.jpg"/>  
      <media:thumbnail width="203" height="152" url="http://news.bbcimg.co.uk/media/images/48930000/jpg/_48930745_010076484-1.jpg"/>  
      <media:thumbnail width="226" height="170" url="http://news.bbcimg.co.uk/media/images/48929000/jpg/_48929270_010076484-1.jpg"/> 
    </item>  
    <item> 
      <title>Four Israelis killed in West Bank</title>  
      <description>Four Israelis are shot dead in an attack near a settlement in the West Bank, days before peace talks in the US.</description>  
      <link>http://www.bbc.co.uk/go/rss/int/news/-/news/world-middle-east-11144742</link>  
      <guid isPermaLink="false">http://www.bbc.co.uk/news/world-middle-east-11144742</guid>  
      <pubDate>Tue, 31 Aug 2010 19:20:41 GMT</pubDate>  
      <media:thumbnail width="66" height="49" url="http://news.bbcimg.co.uk/media/images/48935000/jpg/_48935780_010019918-1.jpg"/>  
      <media:thumbnail width="203" height="152" url="http://news.bbcimg.co.uk/media/images/48936000/jpg/_48936252_010019918-1.jpg"/>  
      <media:thumbnail width="226" height="170" url="http://news.bbcimg.co.uk/media/images/48935000/jpg/_48935563_010019918-1.jpg"/> 
    </item>  
    <item> 
      <title>Spain busts male-sex traffickers</title>  
      <description>Spanish police break up a trafficking ring which brought mainly Brazilian men to Spain to work as prostitutes.</description>  
      <link>http://www.bbc.co.uk/go/rss/int/news/-/news/world-europe-11142264</link>  
      <guid isPermaLink="false">http://www.bbc.co.uk/news/world-europe-11142264</guid>  
      <pubDate>Tue, 31 Aug 2010 14:58:24 GMT</pubDate>  
      <media:thumbnail width="66" height="49" url="http://news.bbcimg.co.uk/media/images/48931000/gif/_48931558_spain_map6649.gif"/>  
      <media:thumbnail width="203" height="152" url="http://news.bbcimg.co.uk/media/images/48932000/jpg/_48932867_77676055.jpg"/>  
      <media:thumbnail width="226" height="170" url="http://news.bbcimg.co.uk/media/images/48931000/jpg/_48931553_77676055.jpg"/> 
    </item>  
    <!--  removed for clarity -->
    </channel>
</rss>

XSLT Example 1

BBC RSS

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>
          <xsl:value-of select="/rss/channel/title"/>
        </title>
      </head>
      <body>
        <h1><xsl:value-of select="/rss/channel/title"/></h1>
        <p>
          <xsl:value-of select="/rss/channel/description"/>
        </p>
      </body>
    </html>
  </xsl:template>
  
</xsl:stylesheet>

Default Rules for XSLT Processing

XSLT Example 2

BBC RSS

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    indent="yes"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>
          <xsl:value-of select="/rss/channel/title"/>
        </title>
      </head>
      <body>
        <h1>
          <xsl:value-of select="/rss/channel/title"/></h1>
        <p>
          <xsl:value-of select="/rss/channel/description"/>
        </p>
        <xsl:apply-templates select="/rss/channel/item" />
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="item">
    <p>
      <a href="{link}">
        <xsl:value-of select="title"/>
      </a>
      <br/>
      <xsl:value-of select="description"/>
    </p>
  </xsl:template>
  
  <xsl:template match="text()"/>
</xsl:stylesheet>

XSLT Example 3

Note use of:

BBC RSS

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:media="http://search.yahoo.com/mrss" version="1.0">
	<xsl:param name="wantdesc">
		<xsl:value-of select="'yes'" />
	</xsl:param>
	<xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
		doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
		indent="yes" />
	<xsl:template match="/">
		<html>
			<head>
				<title>
					<xsl:value-of select="/rss/channel/title" />
				</title>
				<meta name="description" content="{/rss/channel/description}" />
				<link rel="stylesheet" type="text/css" href="rssstyle.css" />
			</head>
			<body>
				<h1>
					<a href="{normalize-space(/rss/channel/link)}">
						<xsl:value-of select="/rss/channel/title" />
					</a>
				</h1>
				<div class="description">
					<xsl:value-of select="/rss/channel/description" />
				</div>
				<xsl:apply-templates />
				<hr />
				<p>
					<xsl:call-template name="validxhtml" />
					<xsl:call-template name="validcss" />
				</p>
			</body>
		</html>
	</xsl:template>
	
	<xsl:template match="channel">
		<xsl:apply-templates select="item" />
	</xsl:template>
	
	<xsl:template match="item">
		<div class="item">
			<div class="rsstitle">
				<a>
					<xsl:attribute name="href">
            <xsl:value-of select="link" />
          </xsl:attribute>
					<xsl:value-of select="title" />
				</a>
			</div>
			<xsl:if test="$wantdesc = 'yes' ">
				<div class="rssdescription">
					<xsl:apply-templates select="media:thumbnail[position() = 1]" />
					<xsl:value-of select="description" />
				</div>
			</xsl:if>
		</div>
	</xsl:template>
	
	<xsl:template match="media:thumbnail">
		<img class="itemthumbnail" src="{@url}" alt="thumbnail" />
	</xsl:template>
	
	<xsl:template match="text()" />
	
	<xsl:template name="validxhtml">
		<a href="http://validator.w3.org/check/referer">
			<img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!"
				height="31" width="88" />
		</a>
	</xsl:template>
	
	<xsl:template name="validcss">
		<a href="http://jigsaw.w3.org/css-validator/check/referer">
			<img src="http://jigsaw.w3.org/css-validator/images/vcss" height="31"
				width="88" alt="Valid CSS!" />
		</a>
	</xsl:template>
</xsl:stylesheet>

The Simplest XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:media="http://search.yahoo.com/mrss" version="1.0">
	
</xsl:stylesheet>

Default Rules Illustrated

The result:

Common XSLT elements

xsl:template

Defines a template that will contain rules to process nodes that "match" the template.

xsl:apply-templates

select list of nodes to apply templates to

When you think about XSL, think in terms of recursion! Don't loop, recurse!

xsl:value-of

output a value of a selected node or expression

Push vs. Pull

Push - Primarily XML SourceDocument Driven

XSLT Processor "pushes" XML content to XSL document. Templates are defined for elements.

Critical for document structures that are highly "nested" or hierarchical.

Pull - Primarily XSLT Stylesheet Drive

XSL document "pulls" content from XML document.

"Pull" Example - Weather

kbos

Weather XML:

<current_observation version="1.0"
	 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xsi:noNamespaceSchemaLocation="http://www.weather.gov/view/current_observation.xsd">
	<credit>NOAA's National Weather Service</credit>
	<credit_URL>http://weather.gov/</credit_URL>
	<image>
		<url>http://weather.gov/images/xml_logo.gif</url>
		<title>NOAA's National Weather Service</title>

		<link>http://weather.gov</link>
	</image>
	<suggested_pickup>15 minutes after the hour</suggested_pickup>
	<suggested_pickup_period>60</suggested_pickup_period>
	<location>Boston, Logan International Airport, MA</location>
	<station_id>KBOS</station_id>

	<latitude>42.38</latitude>
	<longitude>-71.03</longitude>
	<observation_time>Last Updated on Sep 7 2010, 11:54 am EDT</observation_time>
        <observation_time_rfc822>Tue,  7 Sep 2010 11:54:00 -0400</observation_time_rfc822>
	<weather>Partly Cloudy</weather>
	<temperature_string>80.0 F (26.7 C)</temperature_string>

	<temp_f>80.0</temp_f>
	<temp_c>26.7</temp_c>
	<relative_humidity>52</relative_humidity>
	<wind_string>from the Southwest at 13.8 gusting to 18.4 MPH (12 gusting to 16 KT)</wind_string>
	<wind_dir>Southwest</wind_dir>
	<wind_degrees>230</wind_degrees>

	<wind_mph>13.8</wind_mph>
	<wind_gust_mph>18.4</wind_gust_mph>
	<wind_kt>12</wind_kt>
	<wind_gust_kt>16</wind_gust_kt>
	<pressure_string>1019.0 mb</pressure_string>
	<pressure_mb>1019.0</pressure_mb>

	<pressure_in>30.09</pressure_in>
	<dewpoint_string>61.0 F (16.1 C)</dewpoint_string>
	<dewpoint_f>61.0</dewpoint_f>
	<dewpoint_c>16.1</dewpoint_c>
	<heat_index_string>81 F (27 C)</heat_index_string>
      	<heat_index_f>81</heat_index_f>

      	<heat_index_c>27</heat_index_c>
	<visibility_mi>10.00</visibility_mi>
 	<icon_url_base>http://weather.gov/weather/images/fcicons/</icon_url_base>
	<two_day_history_url>http://www.weather.gov/data/obhistory/KBOS.html</two_day_history_url>
	<icon_url_name>sct.jpg</icon_url_name>
	<ob_url>http://www.nws.noaa.gov/data/METAR/KBOS.1.txt</ob_url>

	<disclaimer_url>http://weather.gov/disclaimer.html</disclaimer_url>
	<copyright_url>http://weather.gov/disclaimer.html</copyright_url>
	<privacy_policy_url>http://weather.gov/notice.html</privacy_policy_url>
</current_observation>
    

Weather XSL:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<html>
			<head>
				<title>Weather conditions for
					<xsl:value-of select="/current_observation/location"/>
				</title>
			</head>
			<body>
				<xsl:apply-templates/>
			</body>
		</html>
	</xsl:template>

	<xsl:template match="current_observation">
		<h1>
			<xsl:value-of select="location"/>
		</h1>
		<p>
			<img src="{icon_url_base}{icon_url_name}" alt="weather icon"/>
			<br/>
			<xsl:value-of select="weather"/>
		</p>

		<p class="temp">
			<xsl:value-of select="temp_f"/>&#xB0;F</p>
	</xsl:template>

</xsl:stylesheet>

"Push" Example

A project directory structure:
directory structure

The XML representation:

<dir:directory xmlns:dir="http://apache.org/cocoon/directory/2.0"
  name="example_project_d" lastModified="1184877908187" date="7/19/07 4:45 PM"
  size="0" sort="name" reverse="false" requested="true">
  <dir:directory name="data" lastModified="1184878459125" date="7/19/07 4:54 PM"
    size="0">
    <dir:file name="codes.xml" lastModified="1184879185234" date="7/19/07 5:06 PM"
      size="396"/>
    <dir:file name="data.xml" lastModified="1184878478031" date="7/19/07 4:54 PM"
      size="160"/>
    <dir:file name="people.xml" lastModified="1184760396671" date="7/18/07 8:06 AM"
      size="290213"/>
    <dir:file name="usps.xml" lastModified="1152812736634" date="7/13/06 1:45 PM"
      size="2857"/>
  </dir:directory>
  <dir:file name="sitemap.xmap" lastModified="1184879839703" date="7/19/07 5:17 PM"
    size="5984"/>
  <dir:directory name="web" lastModified="1184877908296" date="7/19/07 4:45 PM"
    size="0">
    <dir:directory name="css" lastModified="1184877908312" date="7/19/07 4:45 PM"
      size="0">
      <dir:file name="site.css" lastModified="1184951237765" date="7/20/07 1:07 PM"
        size="2057"/>
    </dir:directory>
    <dir:directory name="html" lastModified="1184877908343" date="7/19/07 4:45 PM"
      size="0">
      <dir:file name="index.html" lastModified="1185199124750"
        date="7/23/07 9:58 AM" size="2320"/>
      <dir:file name="party.html" lastModified="1185199105656"
        date="7/23/07 9:58 AM" size="2184"/>
      <dir:file name="state.html" lastModified="1185199078812"
        date="7/23/07 9:57 AM" size="2034"/>
      <dir:file name="type.html" lastModified="1185199113453"
        date="7/23/07 9:58 AM" size="2321"/>
    </dir:directory>
    <dir:directory name="images" lastModified="1184877908343"
      date="7/19/07 4:45 PM" size="0">
      <dir:file name="flag-background.png" lastModified="1141750578707"
        date="3/7/06 11:56 AM" size="31307"/>
    </dir:directory>
    <dir:directory name="yui" lastModified="1185198957609" date="7/23/07 9:55 AM"
      size="0">
      <dir:directory name="reset-fonts-grids" lastModified="1184877910359"
        date="7/19/07 4:45 PM" size="0">
        <dir:file name="README" lastModified="1184809030093" date="7/18/07 9:37 PM"
          size="481"/>
        <dir:file name="reset-fonts-grids.css" lastModified="1184809030093"
          date="7/18/07 9:37 PM" size="3260"/>
      </dir:directory>
    </dir:directory>
  </dir:directory>
  <dir:directory name="xsl" lastModified="1184877908312" date="7/19/07 4:45 PM"
    size="0">
    <dir:directory name="data" lastModified="1184878402921" date="7/19/07 4:53 PM"
      size="0">
      <dir:file name="filter.xsl" lastModified="1184951553890"
        date="7/20/07 1:12 PM" size="4515"/>
      <dir:file name="group.xsl" lastModified="1185308266937"
        date="7/24/07 4:17 PM" size="2248"/>
    </dir:directory>
    <dir:directory name="fo" lastModified="1184877908468" date="7/19/07 4:45 PM"
      size="0">
      <dir:file name="list.xsl" lastModified="1184703070138" date="7/17/07 4:11 PM"
        size="9877"/>
    </dir:directory>
    <dir:directory name="xhtml" lastModified="1184880292062" date="7/19/07 5:24 PM"
      size="0">
      <dir:file name="common-lite.xsl" lastModified="1184872501281"
        date="7/19/07 3:15 PM" size="2714"/>
      <dir:file name="common.xsl" lastModified="1184880565265"
        date="7/19/07 5:29 PM" size="3369"/>
      <dir:file name="detail.xsl" lastModified="1185240453968"
        date="7/23/07 9:27 PM" size="3186"/>
      <dir:file name="grid.xsl" lastModified="1185240280187" date="7/23/07 9:24 PM"
        size="1133"/>
      <dir:file name="list.xsl" lastModified="1184950989625" date="7/20/07 1:03 PM"
        size="2201"/>
      <dir:file name="lite.xsl" lastModified="1184876576046" date="7/19/07 4:22 PM"
        size="1433"/>
      <dir:file name="person.xsl" lastModified="1185240430140"
        date="7/23/07 9:27 PM" size="2042"/>
      <dir:file name="static.xsl" lastModified="1184813975937"
        date="7/18/07 10:59 PM" size="601"/>
    </dir:directory>
    <dir:directory name="xls" lastModified="1184877908515" date="7/19/07 4:45 PM"
      size="0">
      <dir:file name="list.xsl" lastModified="1184695422762" date="7/17/07 2:03 PM"
        size="2537"/>
    </dir:directory>
  </dir:directory>
</dir:directory>

"Push" Example 1

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:dir="http://apache.org/cocoon/directory/2.0"
  xmlns="http://www.w3.org/1999/xhtml" version="1.0">
  
  <xsl:template match="/">
    <html>
      <head>
        <title>Project Directory Structure</title>
        <link rel="stylesheet" type="text/css" href="push.css"/>
      </head>
      <body>
        <h1>Project Directory Structure</h1>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="dir:directory">
    <div class="directory">
      <xsl:value-of select="@name"/>
    </div>
  </xsl:template>

</xsl:stylesheet>

"Push" Example 2

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:dir="http://apache.org/cocoon/directory/2.0"
  xmlns="http://www.w3.org/1999/xhtml" version="1.0">
  
  <xsl:template match="/">
    <html>
      <head>
        <title>Project Directory Structure</title>
        <link rel="stylesheet" type="text/css" href="push.css"/>
      </head>
      <body>
        <h1>Project Directory Structure</h1>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="dir:directory">
    <div class="directory">
      <xsl:value-of select="@name"/>
      <xsl:apply-templates/>
    </div>
  </xsl:template>

</xsl:stylesheet>

XHTML result:

<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:dir="http://apache.org/cocoon/directory/2.0">
  <head>
    <title>Project Directory Structure</title>
    <link href="push.css" type="text/css" rel="stylesheet"/>
  </head>
  <body>
    <h1>Project Directory Structure</h1>
    <div class="directory">example_project_d
      <div class="directory">data</div>
      <div class="directory">web
        <div class="directory">css</div>
        <div class="directory">html</div>
        <div class="directory">images</div>
        <div class="directory">yui
          <div class="directory">reset-fonts-grids</div></div></div>
      <div class="directory">xsl
        <div class="directory">data</div>
        <div class="directory">fo</div>
        <div class="directory">xhtml</div>
        <div class="directory">xls</div></div></div>
  </body>
</html>

"Push" Example 3

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:dir="http://apache.org/cocoon/directory/2.0"
  xmlns="http://www.w3.org/1999/xhtml" version="1.0">
  
  <xsl:template match="/">
    <html>
      <head>
        <title>Project Directory Structure</title>
        <link rel="stylesheet" type="text/css" href="push.css"/>
      </head>
      <body>
        <h1>Project Directory Structure</h1>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="dir:directory">
    <div class="directory">
      <xsl:value-of select="@name"/>
      <xsl:apply-templates/>
    </div>
  </xsl:template>
  
  <xsl:template match="dir:file">
    <div class="file">
      <xsl:value-of select="@name"/>
    </div>
  </xsl:template>
  
</xsl:stylesheet>

XPath

Node Types

Axes

Axis is indicated by "axis_name::element_name"
attribute::* selects all attribute nodes of the current element.

XPath Axes

Image from Nornman Walsh, http://nwalsh.com/docs/tutorials/xsl/xsl/foil22.html

xpath axes

XPath Predicates

Predicates are filters that restrict the nodes selected by an XPath expression. Predicates appear inside [square brackets].

Predicates can appear with any XPath statement -- in the "match" of an xsl:template as well as a "select" attribute.

You can "chain" predicates

  1. /rss/channel/item[1]
  2. /rss/channel/item[last()]
  3. /rss/channel/item[position() mod 2 = 0]
  4. /rss/channel/item[position() mod 2 = 0]/title
  5. /rss/channel/item[1]/title
  6. /fas_courses/course[@acad_year = 2010][@offered = 'Y']
  7. /fas_courses/course[@acad_year = 2010 and @offered = 'Y']
  8. /html/body//a[@href]

What is the difference between the following?

XPath Functions

We'll be speaking more about these in the future. A list of the 27 functions in XPath 1.0:

Identify External Links

Problem: identify the external links in an XHTML document

simple

Solution:

simple

CSS and External Links

CSS definition:

a.external  {
  padding: 0 30px 0px 0px;
  display:inline;
  background-repeat: no-repeat;
  background-position: center right;
  background-image: url(../images/external.png);
}

Plain links:

A bonus of attending Harvard University Extension School is being able to enjoy Harvard Square in Cambridge, Massachusetts.

<p>A bonus of attending 
<a href="http://www.extension.harvard.edu/">Harvard University Extension School</a> 
is being able to enjoy <a href="http://www.harvardsquare.com/">Harvard Square</a> 
in <a href="http://www.cambridgema.gov/">Cambridge</a>, 
<a href="http://www.mass.gov">Massachusetts</a>. </p>

External links exposed:

A bonus of attending Harvard University Extension School is being able to enjoy Harvard Square in Cambridge, Massachusetts.

<p>A bonus of attending 
<a href="http://www.extension.harvard.edu/">Harvard University Extension School</a> 
is being able to enjoy 
<a class="external" href="http://www.harvardsquare.com/">Harvard Square</a> 
in <a class="external" href="http://www.cambridgema.gov/">Cambridge</a>, 
<a class="external" href="http://www.mass.gov">Massachusetts</a>. </p>

Using XSLT to Copy

XSLT provides two ways to copy:

Shallow copy - "xsl:copy"

The following is an identity transformation:

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|child::node()"/>
  </xsl:copy>
</xsl:template>

Deep copy - "xsl:copy-of"

The following copies everything:

<xsl:template match="/">
  <xsl:copy-of select="." />
</xsl:template>

Copying with Some Alterations

We want almost an identity transformation -- except we want to place the class="external" for external links.

<!-- template to match external link -->
<!-- starts-with(@href,'http') tests for absolute URL -->
<!-- contains(@href,'.harvard.edu') tests for links within domain -->
<!-- not() works as expected -->
<xsl:template match="h:a[
  starts-with(@href,'http') and 
  not(contains(@href,'.harvard.edu'))
  ]">
  <xsl:copy>
    <xsl:attribute name="class">
      <xsl:value-of select="'external'"/>
    </xsl:attribute>
    <xsl:apply-templates select="@*|child::node()"/>
  </xsl:copy>
</xsl:template>

<!-- identity transform -->
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|child::node()"/>
  </xsl:copy>
</xsl:template>

Example

<p>A bonus of attending
    <a href="http://www.extension.harvard.edu/" shape="rect">Harvard University
      Extension School</a> is being able to enjoy
    <a class="external" href="http://www.harvardsquare.com/">Harvard
      Square</a> in
    <a class="external" href="http://www.cambridgema.gov/">
      Cambridge</a>,
    <a class="external" href="http://www.mass.gov">Massachusetts</a>.
  </p>

Templates and Modes

Definition: Modes allow a node in a source tree to be processed multiple times, each time producing a different result. They also allow different sets of template rules to be active when processing different trees, for example when processing documents loaded using the document function (see 16.1 Multiple Source Documents) or when processing temporary trees.

TOC for an XHTML document

Problem: Insert a table of contents into an XHTML document. The TOC should be derived from the content of the XHTML document.

Solution:

Notes:

Input, XSL, and Output:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:h="http://www.w3.org/1999/xhtml"
  xmlns="http://www.w3.org/1999/xhtml"
  exclude-result-prefixes="h"
  version="1.0">

  <xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="h:body">
    <body>
      <h2>Table of Contents</h2>
      <div style="font-size: 75%;">
        <ul>
          <xsl:apply-templates select="//h:h1|//h:h2|//h:h3" mode="toc"/>
        </ul>
      </div>
      <hr/>
      <xsl:apply-templates select="@*|child::node()"/>
    </body>
  </xsl:template>

  <xsl:template match="h:h2|h:h1|h:h3">
    <xsl:element name="{local-name()}">
        <xsl:attribute name="id">
          <xsl:text>toc</xsl:text>
          <xsl:value-of select="
            count(preceding::h:h1) + 
            count(preceding::h:h2) +
            count(preceding::h:h3) + 1"/>
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="h:h1|h:h2|h:h3" mode="toc">
    <li style="margin-left: 15px;">
      <a>
        <xsl:attribute name="href">
          <xsl:text>#toc</xsl:text>
          <xsl:value-of select="position()"/>
        </xsl:attribute>
        <xsl:value-of select="."/>
      </a>
    </li>
  </xsl:template>

  <xsl:template match="@*|*">
    <xsl:copy>
      <xsl:apply-templates select="@*|child::node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Variables: xsl:variable

Variable containing a string:
<xsl:variable name="coursename">
  CSCI E-153 Web Development Using XML
</xsl:variable>
...
<xsl:template match="/>
    <html>
      <head>
        <title>
          <xsl:value-of select="$coursename"/>
        </title>
      </head>
      <body>
        <h1>
          <xsl:value-of select="$coursename"/>
        </h1>
        <xsl:apply-templates/>
      </body>
    </html>
</xsl:template>
Variable containing a node-set:
<xsl:variable name="fall2010">
  <xsl:value-of 
    select="/courses/course[@acad_year = 2010][@term_id = 1]"/>
</xsl:variable>

Why variables?

Parameters: xsl:param

Two types of parameters:

Local Parameters

Defining parameters (xsl:param)
Referencing parameters ($param_name)

<xsl:template name="maketable">
  <xsl:param name="myclass" select="'grid'" />
  <table class="{$myclass}">
  <xsl:apply-templates select="person" mode="row"/>
  </table>
</xsl:template>

Passing parameters (xsl:with-param)

<xsl:call-template name="maketable">
  <xsl:with-param name="myclass" select="'plain'" />
</xsl:call-template>

Global Parameters

Global parameters can be very powerful in making your stylesheets flexible.

  1. define parameters in XSLT
  2. pass them in via the environment

Define and Use Parameters in XSLT

Use xsl:param as child of xsl:stylesheet

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:param name="show_url" select="'no'" />
      <xsl:template>
  ...

Conditionally process...

  <xsl:template match="link[parent::item]">
    <xsl:if test="$showurl eq 'yes'">
      <div class="link">
        <a href="{parent::item/link}">
          <xsl:value-of select="text()"/>
        </a>
      </div>
    </xsl:if>
  </xsl:template>  

Parameters in XSLT

These examples use an XML file containing information about members of the United States Congress.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" doctype-system="http://www.w3.org/TR/html401/loose.dtd"/>
  <xsl:variable name="evencolor">#bbbbff</xsl:variable>
  <xsl:variable name="oddcolor">#eeeeee</xsl:variable>
  <xsl:variable name="displaytitle">United States Congress</xsl:variable>
  <xsl:param name="ST"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>
          <xsl:value-of select="$displaytitle"/>
        </title>
        <xsl:call-template name="style"/>
      </head>
      <body>
        <h1><xsl:value-of select="$displaytitle"/></h1>
        <h2>Members from
          <xsl:value-of select="$ST"/></h2>
        <table width="100%">
          <tr>
            <th>Full Name</th>
            <th>State</th>
            <th>District</th>
            <th>Party</th>
          </tr>
          <xsl:apply-templates select="/people/person[@state = $ST]">
            <xsl:sort select="@title"/>
            <xsl:sort select="@lastname"/>
            <xsl:sort select="@firstname"/>
          </xsl:apply-templates>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="person">
    <tr>
      <xsl:choose>
        <xsl:when test="position() mod 2">
          <xsl:attribute name="class"><xsl:value-of select="'oddrow'"/></xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="class"><xsl:value-of select="'evenrow'"/></xsl:attribute>
        </xsl:otherwise>
      </xsl:choose>
      <td>
        <xsl:value-of select="@name"/>
      </td>
      <td>
        <xsl:value-of select="@state"/>
      </td>
      <td>
        <xsl:value-of select="@district"/>
      </td>        
      <td>
        <xsl:value-of select="role/@party"/>
      </td>
    </tr>
  </xsl:template>

  <xsl:template name="style">
    <style type="text/css">
      tr.evenrow {background-color: <xsl:value-of select="$evencolor"/>;} 
      tr.oddrow {background-color: <xsl:value-of select="$oddcolor"/>;} 
      body {font-family: Arial, Helvetica,sans-serif;} 
      h1,h2,h3,h4,h5,h6 {text-align: center;} 
    </style>
  </xsl:template>
</xsl:stylesheet>

Sorting in XSLT

These examples use an XML file containing information about members of the United States Congres.

Document Order

<xsl:apply-templates select="/people/person" />

Sorting

xsl:sort can be the first child of an xsl:apply-templates:

<xsl:apply-templates select="/people/person">
  <xsl:sort select="@lastname"/>    
  <xsl:sort select="@firstname"/>    
</xsl:apply-templates>

Sorting

xsl:sort can be the first child of an xsl:apply-templates:

<xsl:apply-templates select="/people/person">
  <xsl:sort select="@state"/>    
  <xsl:sort select="@lastname"/>    
  <xsl:sort select="@firstname"/>    
</xsl:apply-templates>

Numeric Sorting

Can also sort numerically:

<xsl:apply-templates select="/people/person[role/@type = 'rep']">
  <xsl:sort select="role/@state"/>
  <xsl:sort select="role/@district" data-type="number"/>
</xsl:apply-templates>

Control Structures

xsl:if

<xsl:template match="link[parent::item]">
  <xsl:if test="$showurl eq 'yes'">
    <div class="link">
      <a href="{parent::item/link}">
        <xsl:value-of select="text()"/>
      </a>
    </div>
  </xsl:if>
</xsl:template>

xsl:choose

<xsl:choose>
  <xsl:when test="$ST">
    <xsl:apply-templates select="/people/person[@state = $ST]"/>
  </xsl:when>
  <!-- can have multiple xsl:when -->
  <xsl:otherwise>
    <xsl:apply-templates select="/people/person"/>
  </xsl:otherwise>
</xsl:choose>

Camels, Lamas, Giraffes and Okapis ... and XML!

camel   lama

giraffe  okapi

Biological Taxonomy

Background (if interested):


My Simplified Dataset

     <taxonomy>
      <kingdom name="Animalia" common="animals">
        <phylum name="Acanthocephala"/>
        <phylum name="Chordata" common="cordates">
          <class name="Actinopterygii"/>
          <class name="Amphibia"/>
          <class name="Reptilia"/>
          <class name="Mammalia" common="mammals">
            <order name="Afrosoricida" />
            <order name="Artiodactyla" common="even-toed ungulates">
              <family name="Antilocapridae">
                <genus name="Antilocapra">
                  <species name="Antilocapra americana"/>
                </genus>
              </family>
              <family name="Bovidae">
                <genus name="Addax"/>
                <genus name="Antilope"/>
                <genus name="Bison"/>
                <genus name="Gazella"/>
                <!-- more not shown -->
              </family>
              <family name="Camelidae">
                <genus name="Camelus" common="camels">
                  <species name="Camelus bactrianus"/>
                  <species name="Camelus dromedarius"/>
                </genus>
                <genus name="Lama">
                  <species name="Lama glama"/>
                  <species name="Lama guanicoe"/>
                  <species name="Lama pacos"/>
                </genus>
                <genus name="Vicugna">
                  <species name="Vicugna vicugna"/>
                </genus>
              </family>
              <family name="Cervidae"/>
              <family name="Giraffidae" common="giraffes">
                <genus name="Giraffa">
                  <species name="Giraffa camelopardalis"/>
                </genus>
                <genus name="Okapia">
                  <species name="Okapia johnstoni"/>
                </genus>
              </family>
              <family name="Hippopotamidae"/>
              <family name="Moschidae"/>
              <family name="Suidae"/>
              <family name="Tayassuidae"/>
              <family name="Tragulidae"/>
            </order>
            <order name="Carnivora" />
            <order name="Cetacea" />
            <order name="Chiroptera" />
            <order name="Cingulata" />
            <!-- more not shown -->
          </class>
          <!-- more not shown -->
        </phylum>
        <phylum name="Mollusca"/>
        <!-- more not shown -->
      </kingdom>
      <kingdom name="Archaea"/>
      <kingdom name="Bacteria"/>
      <kingdom name="Chromista"/>
      <kingdom name="Fungi"/>
      <kingdom name="Plantae"/>
      <kingdom name="Protozoa"/>
      <kingdom name="Viruses"/>
    </taxonomy>

Finding Others in the same Genus, Approach 1

Approach: select all the species in the same genus.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:param name="myspecies" select="'Lama guanicoe'"/>
    <xsl:template match="/">
        <html>
            <head>
                <title>Biological Taxonomy</title>
            </head>
            <body>
                <xsl:apply-templates />
            </body>
        </html>
    </xsl:template>

    <xsl:template match="taxonomy">
        <p>
            <strong>
                <xsl:text>Species in the same genus as </xsl:text>
                <em>
                    <xsl:value-of select="$myspecies"/>
                </em>
            </strong>
        </p>
        <xsl:apply-templates select="//genus[species/@name=$myspecies]"/>
    </xsl:template>

    <xsl:template match="species">
        <p>
            <xsl:value-of select="@name"/>
        </p>
    </xsl:template>

    <xsl:template match="*">
        <xsl:comment>
            <xsl:value-of select="concat(local-name(),' ',@name)"/>
        </xsl:comment>
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

    

Approach 2

Approach: template that matches on species with the same parent genus

   <xsl:template match="taxonomy">
      <p>
        <strong>
          <xsl:text>Species in the same genus as </xsl:text>
          <em>
            <xsl:value-of select="$myspecies"/>
          </em>
        </strong>
      </p>
      <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="species[parent::genus/species/@name=$myspecies]">
      <p>
        <xsl:value-of select="@name"/>
      </p>
    </xsl:template>

Approach 3

Approach: Select the species and then use the "preceding-sibling" and "following-sibling" axes.

    <xsl:template match="taxonomy">
        <p>
            <strong>
                <xsl:text>Species in the same genus as </xsl:text>
                <em>
                    <xsl:value-of select="$myspecies"/>
                </em>
            </strong>
        </p>
        <xsl:apply-templates select="//species[@name=$myspecies]"/>
    </xsl:template>

    <xsl:template match="species">
        <xsl:apply-templates select="preceding-sibling::species" mode="display"/>
        <p>
            <xsl:value-of select="@name"/>
        </p>
        <xsl:apply-templates select="following-sibling::species" mode="display"/>
    </xsl:template>

    <xsl:template match="species" mode="display">
        <p>
            <xsl:value-of select="@name"/>
        </p>
    </xsl:template>

Building a Hierarchy

Strategy: use templates and xsl:apply-templates to recursively go through document.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:template match="/">
        <html>
            <head>
                <title>Biological Taxonomy</title>
            </head>
            <body>
                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="taxonomy">
        <p>
            <strong>
                <xsl:text>Tree</xsl:text>
            </strong>
        </p>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="*">
        <div style="margin-left: 10px;">
            <strong>
                <xsl:value-of select="local-name()"/>
            </strong>
            <xsl:text>:  </xsl:text>
            <xsl:value-of select="@name"/>
            <xsl:apply-templates/>
        </div>
    </xsl:template>
</xsl:stylesheet>

Tree 'pruned' to a specific species

Approach: select only those parts of the tree that have the species as a descendant

    <xsl:template match="taxonomy">
        <p>
            <strong>
                <xsl:text>Tree</xsl:text>
            </strong>
        </p>
        <xsl:apply-templates select="kingdom[descendant::species/@name=$myspecies]"/>
    </xsl:template>

    <xsl:template match="*">
        <div style="margin-left: 10px;">
            <strong><xsl:value-of select="local-name()"/></strong>
            <xsl:text>:  </xsl:text>
            <xsl:value-of select="@name"/>
            <xsl:apply-templates select="*[descendant-or-self::species/@name=$myspecies]"/>
        </div>
    </xsl:template>

A Flat Tree 'pruned' to a specific species

Approach: select the species node, then select all of its ancestors.

    <xsl:template match="taxonomy">
        <p>
            <strong>
                <xsl:text>A Flat Tree</xsl:text>
            </strong>
        </p>
        <xsl:apply-templates select="//species[@name=$myspecies]"/>
    </xsl:template>
        
    <xsl:template match="species">
        <xsl:for-each select="ancestor-or-self::*">
            <p>
                <strong>
                    <xsl:value-of select="local-name()"/>
                </strong>
                <xsl:text>:  </xsl:text>
                <xsl:value-of select="@name"/>
            </p>
        </xsl:for-each>
    </xsl:template>

A Tree 'pruned' to show ancestors and descendants at any level

Approach: template to match on ancestor or descendant or self of the 'level'.

    <xsl:template match="*[
        ancestor::*[@name=$mygroup] or 
        descendant-or-self::*[@name=$mygroup]
        ]">
        <div style="margin-left: 10px;">
            <span>
                <xsl:attribute name="class">
                <xsl:choose>
                  <xsl:when test="@name eq $mygroup">current</xsl:when>
                  <xsl:otherwise>default</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <strong><xsl:value-of select="local-name()"/></strong>
            <xsl:text>:  </xsl:text>
            <xsl:value-of select="@name"/></span>
            <xsl:apply-templates />
        </div>
    </xsl:template>

Copyright © 2002-2010 David P. Heitmeyer

Bookmark and Share