diff --git a/src/main/java/info/textgrid/services/aggregator/Help.java b/src/main/java/info/textgrid/services/aggregator/Help.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a751c3d712f4e3ac6706a0468c85c0468d02406
--- /dev/null
+++ b/src/main/java/info/textgrid/services/aggregator/Help.java
@@ -0,0 +1,59 @@
+package info.textgrid.services.aggregator;
+
+import info.textgrid.services.aggregator.util.StylesheetManager;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriBuilderException;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.transform.stream.StreamSource;
+
+import net.sf.saxon.s9api.QName;
+import net.sf.saxon.s9api.SaxonApiException;
+import net.sf.saxon.s9api.Serializer;
+import net.sf.saxon.s9api.XdmAtomicValue;
+import net.sf.saxon.s9api.XsltTransformer;
+
+import com.google.common.base.Optional;
+
+public class Help implements StreamingOutput {
+
+	private final StylesheetManager stylesheetManager;
+	private final URL wadlURL;
+
+	public Help(StylesheetManager stylesheetManager, UriInfo uriInfo) {
+		this.stylesheetManager = stylesheetManager;
+		try {
+			wadlURL = uriInfo.getBaseUriBuilder().queryParam("_wadl").build().toURL();
+		} catch (final MalformedURLException e) {
+			throw new WebApplicationException(e);
+		} catch (final IllegalArgumentException e) {
+			throw new WebApplicationException(e);
+		} catch (final UriBuilderException e) {
+			throw new WebApplicationException(e);
+		}
+	}
+
+	@Override
+	public void write(OutputStream output) throws IOException,
+			WebApplicationException {
+		try {
+			final XsltTransformer transformer = stylesheetManager.getStylesheet(URI.create("/WEB-INF/stylesheets/wadl_documentation-2009-02.xsl"), Optional.<String>absent(), false, false).load();
+			final Serializer serializer = stylesheetManager.xsltProcessor.newSerializer(output);
+			transformer.setDestination(serializer);
+			transformer.setSource(new StreamSource(wadlURL.openStream(), wadlURL.toString()));
+			transformer.setParameter(new QName("apptitle"), new XdmAtomicValue("TextGrid Aggregator Service"));
+			transformer.transform();
+		} catch (final SaxonApiException e) {
+			throw new WebApplicationException(e);
+		}
+
+	}
+
+}
diff --git a/src/main/java/info/textgrid/services/aggregator/REST.java b/src/main/java/info/textgrid/services/aggregator/REST.java
index 6f83df5312ea102afa68e30a5015b99216885e1f..69889c768eeff94ce81bcfc8b5f8a2f8c876a982 100644
--- a/src/main/java/info/textgrid/services/aggregator/REST.java
+++ b/src/main/java/info/textgrid/services/aggregator/REST.java
@@ -30,6 +30,7 @@
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriInfo;
 
 import net.sf.saxon.s9api.SaxonApiException;
 
@@ -39,12 +40,14 @@
 
 import com.google.common.base.Optional;
 
+@Description(title = "TextGrid Aggregator Service",
+	value = "The Aggregator is a service to export and convert TextGrid documents. It is able to recursively process collections, editions, and other TextGrid aggregations.")
 public class REST {
 
 	private final ITextGridRep repository;
 
-
 	private StylesheetManager stylesheetManager;
+
 	private StylesheetManager getStylesheetManager() {
 		if (stylesheetManager == null)
 			stylesheetManager = new StylesheetManager(servlet, repository);
@@ -54,7 +57,6 @@ private StylesheetManager getStylesheetManager() {
 	@Context
 	private ServletContext servlet;
 
-
 	public REST(final ITextGridRep repository) {
 		this.repository = repository;
 	}
@@ -63,18 +65,20 @@ public REST(final ITextGridRep repository) {
 	@Path("/teicorpus/{uris}")
 	@Produces("application/tei+xml")
 	@Descriptions({
-			@Description(target=DocTarget.METHOD, value="Creates a TEI corpus of all the TEI documents (recursively) aggregated by the given aggregation"),
-			@Description(target=DocTarget.RETURN, value="TEI corpus document")
-	})
-	public Response getCorpus(@Description("TextGrid URIs of the root objects, separated by commas") @PathParam("uris") final String uriList,
+			@Description(target = DocTarget.METHOD, value = "Creates a TEI corpus of all the TEI documents (recursively) aggregated by the given aggregation"),
+			@Description(target = DocTarget.RETURN, value = "TEI corpus document") })
+	public Response getCorpus(
+			@Description("TextGrid URIs of the root objects, separated by commas") @PathParam("uris") final String uriList,
 			@Description("Whether to generate a Content-Disposition: attachment header") @QueryParam("attach") @DefaultValue("true") final boolean attach,
 			@Description("If true, no intermediate TEI corpus documents will be generated for intermediate aggregations, hierarchical structure will be lost") @QueryParam("flat") @DefaultValue("false") final boolean flat,
 			@Description("Title for the container if multiple root objects are given") @QueryParam("title") final String titleArgument,
 			@Description("Session id for accessing restricted resources") @QueryParam("sid") final String sid,
-			@Context final Request request)
-					throws URISyntaxException, ObjectNotFoundFault, MetadataParseFault, IoFault, AuthFault, ProtocolNotImplementedFault, IOException, SaxonApiException {
+			@Context final Request request) throws URISyntaxException,
+			ObjectNotFoundFault, MetadataParseFault, IoFault, AuthFault,
+			ProtocolNotImplementedFault, IOException, SaxonApiException {
 
-		final TEICorpusExporter exporter = new TEICorpusExporter(repository, request, uriList);
+		final TEICorpusExporter exporter = new TEICorpusExporter(repository,
+				request, uriList);
 		exporter.setFlat(flat);
 		exporter.setTitle(titleArgument);
 		exporter.sid(sid);
@@ -82,22 +86,22 @@ public Response getCorpus(@Description("TextGrid URIs of the root objects, separ
 		return exporter.createResponse().build();
 	}
 
-
 	@GET
 	@Path(value = "/epub/{object}")
 	@Produces(value = "application/epub+zip")
 	@Description("Converts the given TEI object or the aggregation of TEI objects to an E-Book in EPUB format")
 	public Response getEPUB(
-			@Description("The TextGrid URI(s) of the object(s) to convert, separated by commas. Should be either TEI objects or aggregations of TEI (and maybe other) objects")
-			@PathParam("object") final String uriList,
+			@Description("The TextGrid URI(s) of the object(s) to convert, separated by commas. Should be either TEI objects or aggregations of TEI (and maybe other) objects") @PathParam("object") final String uriList,
 			@Description("URL of an alternative stylesheet to use. Must be compatible.") @QueryParam("stylesheet") final URI xsluri,
 			@Description("Title if multiple root objects given") @QueryParam("title") final String titleParam,
 			@Description("Session ID for accessing protected objects") @QueryParam("sid") final String sid,
-			@Context final Request request)
-					throws ObjectNotFoundFault, MetadataParseFault, IoFault, AuthFault,
-					ProtocolNotImplementedFault, IOException, SaxonApiException {
+			@Context final Request request) throws ObjectNotFoundFault,
+			MetadataParseFault, IoFault, AuthFault,
+			ProtocolNotImplementedFault, IOException, SaxonApiException {
 
-		final EPUBSerializer serializer = new EPUBSerializer(repository, getStylesheetManager(), uriList, Optional.fromNullable(sid), request);
+		final EPUBSerializer serializer = new EPUBSerializer(repository,
+				getStylesheetManager(), uriList, Optional.fromNullable(sid),
+				request);
 		serializer.setStylesheet(xsluri);
 		serializer.setTitle(titleParam);
 
@@ -107,13 +111,17 @@ public Response getEPUB(
 	@GET
 	@Path(value = "/html/{object}")
 	@Produces(value = "text/html")
+	@Descriptions({
+		@Description(target = DocTarget.METHOD, value = "Generates HTML output. This is typically fast, and it is also used at textgridrep.de.", title = "HTML generator"),
+		@Description(target = DocTarget.RETURN, value = "Either an XHTML document (expect HTML5 elements), or a XHTML fragment containing only the body, if the embedded parameter is true.")
+	})
 	public Response getHTML(
 			@Description("The TextGrid URIs of the TEI document(s) or aggregation(s) to transform, separated by commas") @PathParam("object") final String uriList,
-			@Description("If given, an alternative XSLT stylesheet to use") @QueryParam("stylesheet") final URI xsluri,
-			@Description("If true, check for an <?xsl-stylesheet?> processing instruction in the document to render") @QueryParam("pi") final boolean pi,
+			@Description("If given, an alternative XSLT stylesheet to use. Must be a textgrid URI.") @QueryParam("stylesheet") final URI xsluri,
+			@Description("If true, check for an <?xsl-stylesheet?> processing instruction in the document to render. Only textgrid: URIs will be resolved.") @QueryParam("pi") final boolean pi,
 			@Description("If true and a stylesheet has been given, force reloading the stylesheet, do not cache") @QueryParam("refreshStylesheet") final boolean refreshStylesheet,
 			@Description("Session ID to access protected resources") @QueryParam("sid") final String sid,
-			@Description("If true, pass the information the stylesheet that its result will be embedded into some website") @QueryParam("embedded") final boolean embedded,
+			@Description("If true, an HTML fragment consisting of a <div class='body'> element containing the contents of the HTML <body> will be returned, ready to be embedded in an existing HTML page") @QueryParam("embedded") final boolean embedded,
 			@Description("URL of the CSS that should be referenced in the HTML that is created") @QueryParam("css") final URI css,
 			@Description("The requested content type. E.g., text/html or text/xml") @QueryParam("mediatype") final String mediaType,
 			@Description("An XML ID. If given, only this element will be transformed.") @QueryParam("id") final String id,
@@ -122,51 +130,50 @@ public Response getHTML(
 			ProtocolNotImplementedFault, WebApplicationException, IOException,
 			SaxonApiException, ExecutionException {
 
-
-		final HTMLWriter writer = new HTMLWriter(repository, getStylesheetManager(), uriList, xsluri,
-				refreshStylesheet, pi, embedded, css, sid, mediaType, id, request);
+		final HTMLWriter writer = new HTMLWriter(repository,
+				getStylesheetManager(), uriList, xsluri, refreshStylesheet, pi,
+				embedded, css, sid, mediaType, id, request);
 		return writer.createResponse().build();
 	}
 
 	@GET
 	@Path(value = "/zip/{objects}")
 	@Produces("application/zip")
+	@Descriptions({
+		@Description(target=DocTarget.METHOD, value="Creates a ZIP containing the specified objects and everything that has been aggregated by them, "
+				+ "optionally transformed and filtered. Links within supported XML documents will be rewritten to relative URLs if the target document "
+				+ "is also packed into this ZIP. This method may take quite a while depending on the number of objects, and it will not start "
+				+ "returning something until the metadata for everything that will be exported has been collected, so increase your timeouts ..."),
+		@Description(target=DocTarget.RETURN, value="The ZIP file returned will usually contain a content document plus a sidecar .meta file for each "
+				+ "exported object. The .meta file contains the raw metadata according to the TextGrid metadata schema. For aggregations (editions, "
+				+ "collections), we will typically create both a directory and an ORE content file containing the list of items. "
+				+ "Additionally, a file called /.INDEX.imex will be included in the archive. This file contains the list of exported objects "
+				+ "together with the local filename, the name of the local .meta file, the link rewriting method used, and the original TextGrid URI. "
+				+ "You can use this file to re-import the whole set of files using the TextGridLab. See the Link Rewriter Library's documentation "
+				+ "for an XML schema and description of the format. \n\nThe ZIP file may contain ZIP comments refering to warning or informational "
+				+ "messages during export.")
+	})
 	public Response getZIP(
-			@Description("The TextGridURIs of the TEI documents or aggregations to zip, separated by commas (,)")
-			@PathParam("objects") final String uriList,
-			@Description("Session ID to access protected resources")
-			@QueryParam("sid") final String sid,
-			@Description("(optional) title for the exported data, currently only used for generating the filename. If none is given, the first title of the first object will be used.")
-			@QueryParam("title") final String title,
-			@QueryParam("filenames")
-			@DefaultValue("{parent|/}{author}-{title}*.{ext}")
-			@Description("Pattern for the generated filenames in the ZIP files.") final
-			String filenames,
-			@QueryParam("metanames")
-			@DefaultValue("{filename}.meta")
-			@Description("Pattern for the filenames for the metadata files in the ZIP files.") final
-			String metanames,
-			@QueryParam("dirnames")
-			@DefaultValue("{parent|/}{title}*")
-			@Description("Pattern for the directory names generated for aggregations etc. This pattern applied to the parent aggregation is available as {parent} in filenames and metanames.") final
-			String dirnames,
-
-			@QueryParam("only")
-			@Description("Restrict export to objects with the given MIME types")
-			final List<String> only,
-
-			@QueryParam("meta")
-			@Description("Export metadata and aggregation files")
-			@DefaultValue("true")
-			final boolean meta,
-			
-			@QueryParam("transform")
-			@Description("Transform XML documents")
-			final String transform,
-
-			@Context final Request request) throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault, ProtocolNotImplementedFault, IOException, SaxonApiException {
-
-		final ZipResult zipResult = new ZipResult(repository, getStylesheetManager(), request, uriList, filenames, metanames, dirnames, only, meta, transform);
+			@Description("The TextGridURIs of the TEI documents or aggregations to zip, separated by commas (,)") @PathParam("objects") final String uriList,
+			@Description("Session ID to access protected resources") @QueryParam("sid") final String sid,
+			@Description("(optional) title for the exported data, currently only used for generating the filename. If none is given, the first title of the first object will be used.") @QueryParam("title") final String title,
+			@QueryParam("filenames") @DefaultValue("{parent|/}{author}-{title}*.{ext}") @Description("Pattern for the generated filenames in the ZIP files.") final String filenames,
+			@QueryParam("metanames") @DefaultValue("{filename}.meta") @Description("Pattern for the filenames for the metadata files in the ZIP files.") final String metanames,
+			@QueryParam("dirnames") @DefaultValue("{parent|/}{title}*") @Description("Pattern for the directory names generated for aggregations etc. This pattern applied to the parent aggregation is available as {parent} in filenames and metanames.") final String dirnames,
+
+			@QueryParam("only") @Description("If at least one only parameter is given, restrict export to objects with the given MIME types") final List<String> only,
+
+			@QueryParam("meta") @Description("Include metadata and aggregation files in the ZIP file.") @DefaultValue("true") final boolean meta,
+
+			@QueryParam("transform") @Description("(EXPERIMENTAL) Transform each XML document before zipping. Values currently available are text, html, or the textgrid: URI of an XSLT stylesheet.") final String transform,
+
+			@Context final Request request) throws MetadataParseFault,
+			ObjectNotFoundFault, IoFault, AuthFault,
+			ProtocolNotImplementedFault, IOException, SaxonApiException {
+
+		final ZipResult zipResult = new ZipResult(repository,
+				getStylesheetManager(), request, uriList, filenames, metanames,
+				dirnames, only, meta, transform);
 		if (title != null)
 			zipResult.setTitle(title);
 		if (sid != null)
@@ -177,24 +184,34 @@ public Response getZIP(
 	@GET
 	@Path(value = "/pdf/{object}")
 	@Produces("application/pdf")
-	public Response getPDF(
-			@PathParam("object") final URI uri,
-			@QueryParam("sid") final String sid,
-			@Context final Request request
-			) throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault, ProtocolNotImplementedFault, IOException, SaxonApiException {
-		final PDF pdf = new PDF(repository, getStylesheetManager(), request, uri);
+	@Description("(BROKEN) the PDF export will currently not work on any installed instance of the service.")
+	public Response getPDF(@PathParam("object") final URI uri,
+			@QueryParam("sid") final String sid, @Context final Request request)
+			throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault,
+			ProtocolNotImplementedFault, IOException, SaxonApiException {
+		final PDF pdf = new PDF(repository, getStylesheetManager(), request,
+				uri);
 		pdf.sid(sid);
 		return pdf.createResponse().build();
 
 	}
 
-
 	@GET
 	@Path(value = "/version")
 	@Produces("text/html")
+	@Description("Produces an HTML page containing version and configuration information for the service instance.")
 	public StreamingOutput getVersion() {
 		final Version version = new Version(repository, getStylesheetManager());
 		return version.get();
 	}
 
+	@GET
+	@Path(value = "/help")
+	@Produces("text/html")
+	@Description("Returns an auto-generated help page summarizing all available arguments.")
+	public StreamingOutput getHelp(@Context UriInfo uriInfo) throws SaxonApiException, IOException {
+		return new Help(getStylesheetManager(), uriInfo);
+	}
+
+
 }
diff --git a/src/main/webapp/WEB-INF/stylesheets/wadl_documentation-2009-02.xsl b/src/main/webapp/WEB-INF/stylesheets/wadl_documentation-2009-02.xsl
new file mode 100644
index 0000000000000000000000000000000000000000..dca262864172ccddb412fa5876aeb5d576f4a9a7
--- /dev/null
+++ b/src/main/webapp/WEB-INF/stylesheets/wadl_documentation-2009-02.xsl
@@ -0,0 +1,824 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  wadl_documentation.xsl (2008-12-09)
+
+  An XSLT stylesheet for generating HTML documentation from WADL,
+  by Mark Nottingham <mnot@yahoo-inc.com>.
+
+  Copyright (c) 2006-2008 Yahoo! Inc.
+  
+  This work is licensed under the Creative Commons Attribution-ShareAlike 2.5 
+  License. To view a copy of this license, visit 
+    http://creativecommons.org/licenses/by-sa/2.5/ 
+  or send a letter to 
+    Creative Commons
+    543 Howard Street, 5th Floor
+    San Francisco, California, 94105, USA
+-->
+<!-- 
+ * FIXME
+    - Doesn't inherit query/header params from resource/@type
+    - XML schema import, include, redefine don't import
+-->
+<!--
+  * TODO
+    - forms
+    - link to or include non-schema variable type defs (as a separate list?)
+    - @href error handling
+-->
+
+<xsl:stylesheet 
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
+ xmlns:wadl="http://wadl.dev.java.net/2009/02"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:ns="urn:namespace"
+ xmlns:fn="http://www.textgrid.de/ns/aggregator/fn"
+ xmlns="http://www.w3.org/1999/xhtml"
+ exclude-result-prefixes="xsl wadl xs html ns fn"
+>
+
+    <xsl:output 
+        method="html" 
+        encoding="UTF-8" 
+        indent="yes"
+        doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+    />
+
+    <xsl:variable name="wadl-ns">http://wadl.dev.java.net/2009/02</xsl:variable>
+    <xsl:param name="apptitle">My Web Application</xsl:param>
+    <xsl:param name="prologHtml"/>
+    
+    <!-- expand @hrefs, @types into a full tree -->
+    
+    <xsl:variable name="resources">
+        <xsl:apply-templates select="/wadl:application/wadl:resources" mode="expand"/>
+    </xsl:variable>
+    
+    <xsl:template match="wadl:resources" mode="expand">
+        <xsl:variable name="base">
+            <xsl:choose>
+                <xsl:when test="substring(@base, string-length(@base), 1) = '/'">
+                    <xsl:value-of select="substring(@base, 1, string-length(@base) - 1)"/>
+                </xsl:when>
+                <xsl:otherwise><xsl:value-of select="@base"/></xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <xsl:element name="resources" namespace="{$wadl-ns}">
+            <xsl:for-each select="namespace::*">
+                <xsl:variable name="prefix" select="name(.)"/>
+                <xsl:if test="$prefix">
+                    <xsl:attribute name="ns:{$prefix}"><xsl:value-of select="."/></xsl:attribute>
+                </xsl:if>
+            </xsl:for-each>
+            <xsl:apply-templates select="@*|node()" mode="expand">
+                <xsl:with-param name="base" select="$base"/>
+            </xsl:apply-templates>            
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="wadl:resource[@type]" mode="expand" priority="1">
+        <xsl:param name="base"></xsl:param>
+        <xsl:variable name="uri" select="substring-before(@type, '#')"/>
+        <xsl:variable name="id" select="substring-after(@type, '#')"/>
+        <xsl:element name="resource" namespace="{$wadl-ns}">
+			<xsl:attribute name="path"><xsl:value-of select="@path"/></xsl:attribute>
+            <xsl:choose>
+                <xsl:when test="$uri">
+                    <xsl:variable name="included" select="document($uri, /)"/>
+                    <xsl:copy-of select="$included/descendant::wadl:resource_type[@id=$id]/@*"/>
+                    <xsl:attribute name="id"><xsl:value-of select="@type"/>#<xsl:value-of select="@path"/></xsl:attribute>
+                    <xsl:apply-templates select="$included/descendant::wadl:resource_type[@id=$id]/*" mode="expand">
+                        <xsl:with-param name="base" select="$uri"/>
+                    </xsl:apply-templates>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:copy-of select="//resource_type[@id=$id]/@*"/>
+                    <xsl:attribute name="id"><xsl:value-of select="$base"/>#<xsl:value-of select="@type"/>#<xsl:value-of select="@path"/></xsl:attribute>
+                    <xsl:apply-templates select="//wadl:resource_type[@id=$id]/*" mode="expand">
+                        <xsl:with-param name="base" select="$base"/>                        
+                    </xsl:apply-templates>
+                </xsl:otherwise>
+            </xsl:choose>
+            <xsl:apply-templates select="node()" mode="expand">
+                <xsl:with-param name="base" select="$base"/>
+            </xsl:apply-templates>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="wadl:*[@href]" mode="expand">
+        <xsl:param name="base"></xsl:param>
+        <xsl:variable name="uri" select="substring-before(@href, '#')"/>
+        <xsl:variable name="id" select="substring-after(@href, '#')"/>
+        <xsl:element name="{local-name()}" namespace="{$wadl-ns}">
+            <xsl:copy-of select="@*"/>
+            <xsl:choose>
+                <xsl:when test="$uri">
+                    <xsl:attribute name="id"><xsl:value-of select="@href"/></xsl:attribute>
+                    <xsl:variable name="included" select="document($uri, /)"/>
+                    <xsl:apply-templates select="$included/descendant::wadl:*[@id=$id]/*" mode="expand">
+                        <xsl:with-param name="base" select="$uri"/>
+                    </xsl:apply-templates>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:attribute name="id"><xsl:value-of select="$base"/>#<xsl:value-of select="$id"/></xsl:attribute>
+                    <!-- xsl:attribute name="id"><xsl:value-of select="generate-id()"/></xsl:attribute -->
+                    <xsl:attribute name="element"><xsl:value-of select="//wadl:*[@id=$id]/@element"/></xsl:attribute>
+                    <xsl:attribute name="mediaType"><xsl:value-of select="//wadl:*[@id=$id]/@mediaType"/></xsl:attribute>                    
+                    <xsl:attribute name="status"><xsl:value-of select="//wadl:*[@id=$id]/@status"/></xsl:attribute>                    
+                    <xsl:attribute name="name"><xsl:value-of select="//wadl:*[@id=$id]/@name"/></xsl:attribute>                    
+                    <xsl:apply-templates select="//wadl:*[@id=$id]/*" mode="expand">
+                        <xsl:with-param name="base" select="$base"/>
+                    </xsl:apply-templates>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="node()[@id]" mode="expand">
+        <xsl:param name="base"></xsl:param>
+        <xsl:element name="{local-name()}" namespace="{$wadl-ns}">
+            <xsl:copy-of select="@*"/>
+            <xsl:attribute name="id"><xsl:value-of select="$base"/>#<xsl:value-of select="@id"/></xsl:attribute>
+            <!-- xsl:attribute name="id"><xsl:value-of select="generate-id()"/></xsl:attribute -->
+            <xsl:apply-templates select="node()" mode="expand">
+                <xsl:with-param name="base" select="$base"/>
+            </xsl:apply-templates>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="@*|node()" mode="expand">
+        <xsl:param name="base"></xsl:param>
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()" mode="expand">
+                <xsl:with-param name="base" select="$base"/>
+            </xsl:apply-templates>
+        </xsl:copy>
+    </xsl:template>
+
+<!-- debug $resources
+    <xsl:template match="/">
+    <xsl:copy-of select="$resources"/>
+    </xsl:template>
+-->
+        
+    <!-- collect grammars (TODO: walk over $resources instead) -->
+    
+    <xsl:variable name="grammars">
+        <xsl:copy-of select="/wadl:application/wadl:grammars/*[not(namespace-uri()=$wadl-ns)]"/>
+        <xsl:apply-templates select="/wadl:application/wadl:grammars/wadl:include[@href]" mode="include-grammar"/>
+        <xsl:apply-templates select="/wadl:application/wadl:resources/descendant::wadl:resource[@type]" mode="include-href"/>
+        <xsl:apply-templates select="$resources/descendant::wadl:*[@href]" mode="include-href"/>
+    </xsl:variable>
+        
+    
+    <xsl:template match="wadl:include[@href]" mode="include-grammar">
+        <xsl:variable name="included" select="document(@href, /)/*"></xsl:variable>
+        <xsl:element name="wadl:include">
+            <xsl:attribute name="href"><xsl:value-of select="@href"/></xsl:attribute>
+            <xsl:copy-of select="$included"/> <!-- FIXME: xml-schema includes, etc -->
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="wadl:*[@href]" mode="include-href">
+        <xsl:variable name="uri" select="substring-before(@href, '#')"/>
+        <xsl:if test="$uri">
+            <xsl:variable name="included" select="document($uri, /)"/>
+            <xsl:copy-of select="$included/wadl:application/wadl:grammars/*[not(namespace-uri()=$wadl-ns)]"/>
+            <xsl:apply-templates select="$included/descendant::wadl:include[@href]" mode="include-grammar"/>
+            <xsl:apply-templates select="$included/wadl:application/wadl:resources/descendant::wadl:resource[@type]" mode="include-href"/>
+            <xsl:apply-templates select="$included/wadl:application/wadl:resources/descendant::wadl:*[@href]" mode="include-href"/>
+        </xsl:if>
+    </xsl:template>
+    
+    <xsl:template match="wadl:resource[@type]" mode="include-href">
+        <xsl:variable name="uri" select="substring-before(@type, '#')"/>
+        <xsl:if test="$uri">
+            <xsl:variable name="included" select="document($uri, /)"/>
+            <xsl:copy-of select="$included/wadl:application/wadl:grammars/*[not(namespace-uri()=$wadl-ns)]"/>
+            <xsl:apply-templates select="$included/descendant::wadl:include[@href]" mode="include-grammar"/>
+            <xsl:apply-templates select="$included/wadl:application/wadl:resources/descendant::wadl:resource[@type]" mode="include-href"/>
+            <xsl:apply-templates select="$included/wadl:application/wadl:resources/descendant::wadl:*[@href]" mode="include-href"/>
+        </xsl:if>
+    </xsl:template>
+    
+    <!-- main template -->
+        
+    <xsl:template match="/wadl:application">   
+        <html>
+            <head>
+                <title>
+                    <xsl:choose>
+                        <xsl:when test="wadl:doc[@title]">
+                            <xsl:value-of select="wadl:doc[@title][1]/@title"/>
+                        </xsl:when>
+                        <xsl:otherwise><xsl:value-of select="$apptitle"/></xsl:otherwise>
+                    </xsl:choose>                 
+                </title>
+                <style type="text/css">
+                    body {
+                        font-family: sans-serif;
+                        font-size: 0.85em;
+                        margin: 2em 8em;
+                    }
+                    .methods {
+                        background-color: #ECF4FA;
+                        padding: 1em;
+                    }
+                    h1 {
+                        font-size: 2.5em;
+                        color: #222;
+                        font-weight: normal;
+                    }
+                    h2 {
+                        border-bottom: 1px solid #888;
+                        color: #222;
+                        font-weight: normal;
+                        margin-top: 1em;
+                        margin-bottom: 0.5em;
+                        font-size: 2em;
+                       }
+                    h3 {
+                        color: #3685C4;
+                        font-size: 1.75em;
+                        margin-top: 1.25em;
+                        margin-bottom: 0em;
+                    }
+                    h4 {
+                        margin: 0em;
+                        padding: 0em;
+                        border-bottom: 2px solid white;
+                    }
+                    h6 {
+                        font-size: 1.1em;
+                        color: #99a;
+                        margin: 0.5em 0em 0.25em 0em;
+                    }
+                    a:link {
+                        color: #3685c4;
+                        text-decoration: none;
+                        border-bottom: 1px dashed #56a5e4; 
+                    }
+                    a:visited {
+                        color: #3685c4;
+                        text-decoration: none;                    
+                        border-bottom: 1px dashed #ddd;
+                    }
+                    a:hover {
+                        border-bottom: 1px solid;
+                    }
+                    dd {
+                        margin-left: 1em;
+                    }
+                    tt {
+                        font-size: 1.2em;
+                    }
+                    table {
+                        margin-bottom: 0.5em;
+                    }
+                    th {
+                        text-align: left;
+                        font-weight: normal;
+                        color: black;
+                        border-bottom: 1px solid black;
+                        padding: 3px 6px;
+                    }
+                    td {
+                        padding: 3px 6px;
+                        vertical-align: top;
+                        background-color: f6f6ff;
+                        font-size: 0.85em;
+                    }
+                    td p {
+                        margin: 0px;
+                    }
+                    ul {
+                        padding-left: 1.75em;
+                    }
+                    p + ul, p + ol, p + dl {
+                        margin-top: 0em;
+                    }
+                    .optional {
+                        font-weight: normal;
+                        opacity: 0.75;
+                    }
+                </style>
+            </head>
+            <body>
+                <h1>
+                    <xsl:choose>
+                        <xsl:when test="wadl:doc[@title]">
+                            <xsl:value-of select="wadl:doc[@title][1]/@title"/>
+                        </xsl:when>
+                        <xsl:otherwise><xsl:value-of select="$apptitle"/></xsl:otherwise>
+                    </xsl:choose>
+                </h1>
+                <xsl:value-of select="$prologHtml" disable-output-escaping="yes"/>
+                <xsl:apply-templates select="wadl:doc"/>                
+                <ul>
+                    <li><a href="#resources">Resources</a>
+                        <xsl:apply-templates select="$resources" mode="toc"/>
+                    </li>
+                    <li><a href="#representations">Representations</a>
+                        <ul>
+                            <xsl:apply-templates select="$resources/descendant::wadl:representation" mode="toc"/>
+                        </ul>
+                    </li>
+                    <xsl:if test="descendant::wadl:fault">
+                        <li><a href="#faults">Faults</a>
+                            <ul>
+                                <xsl:apply-templates select="$resources/descendant::wadl:fault" mode="toc"/>
+                            </ul>
+                        </li>
+                    </xsl:if>
+                </ul>
+                <h2 id="resources">Resources</h2>
+                <xsl:apply-templates select="$resources" mode="list"/>
+                <h2 id="representations">Representations</h2>
+                <xsl:apply-templates select="$resources/descendant::wadl:representation" mode="list"/>
+                <xsl:if test="$resources/descendant::wadl:fault"><h2 id="faults">Faults</h2>
+                    <xsl:apply-templates select="$resources/descendant::wadl:fault" mode="list"/>
+                </xsl:if>
+            </body>
+        </html>
+    </xsl:template>
+
+    <!-- Table of Contents -->
+
+    <xsl:template match="wadl:resources" mode="toc">
+        <xsl:variable name="base">
+            <xsl:choose>
+                <xsl:when test="substring(@base, string-length(@base), 1) = '/'">
+                    <xsl:value-of select="substring(@base, 1, string-length(@base) - 1)"/>
+                </xsl:when>
+                <xsl:otherwise><xsl:value-of select="@base"/></xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <ul>
+            <xsl:apply-templates select="wadl:resource" mode="toc">
+                <xsl:with-param name="context"><xsl:value-of select="$base"/></xsl:with-param>
+            </xsl:apply-templates>
+        </ul>        
+    </xsl:template>
+        
+    <xsl:function name="fn:path-join">
+            <xsl:param name="left"/>
+            <xsl:param name="right"/>
+            <xsl:value-of select="$left"/>
+            <xsl:if test="$left != '' and not(ends-with(string-join($left, ''), '/') or starts-with(string-join($right, ''), '/'))">
+                    <xsl:text>/</xsl:text>
+            </xsl:if>
+            <xsl:value-of select="$right"/>
+    </xsl:function>
+
+    <xsl:template match="wadl:resource" mode="toc">
+        <xsl:param name="context"/>
+        <xsl:variable name="id"><xsl:call-template name="get-id"/></xsl:variable>
+        <xsl:variable name="name" select="fn:path-join($context, @path)"/>
+        <li><a href="#{$id}"><xsl:value-of select="$name"/></a>
+        <xsl:if test="wadl:resource">
+            <ul>
+                <xsl:apply-templates select="wadl:resource" mode="toc">
+                    <xsl:with-param name="context" select="$name"/>
+                </xsl:apply-templates>
+            </ul>
+        </xsl:if>
+        </li>
+    </xsl:template>
+
+    <xsl:template match="wadl:representation|wadl:fault" mode="toc">
+        <xsl:variable name="id"><xsl:call-template name="get-id"/></xsl:variable>
+        <xsl:variable name="href" select="@id"/>
+        <xsl:choose>
+            <xsl:when test="preceding::wadl:*[@id=$href]"/> 
+            <xsl:otherwise>               
+                <li>
+                    <a href="#{$id}">
+                        <xsl:call-template name="representation-name"/>
+                    </a>
+                </li>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>        
+
+    <!-- Listings -->
+    
+    <xsl:template match="wadl:resources" mode="list">
+        <xsl:variable name="base">
+            <xsl:choose>
+                <xsl:when test="substring(@base, string-length(@base), 1) = '/'">
+                    <xsl:value-of select="substring(@base, 1, string-length(@base) - 1)"/>
+                </xsl:when>
+                <xsl:otherwise><xsl:value-of select="@base"/></xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <xsl:apply-templates select="wadl:resource" mode="list"/>
+                
+    </xsl:template>
+    
+    <xsl:template match="wadl:resource" mode="list">
+        <xsl:param name="context"/>
+        <xsl:variable name="href" select="@id"/>
+        <xsl:choose>
+            <xsl:when test="preceding::wadl:resource[@id=$href]"/>
+            <xsl:otherwise>
+                <xsl:variable name="id"><xsl:call-template name="get-id"/></xsl:variable>
+                <xsl:variable name="name">
+                    <xsl:value-of select="fn:path-join($context, @path)"/>
+                    <xsl:for-each select="wadl:param[@style='matrix']">
+                        <span class="optional">;<xsl:value-of select="@name"/>=...</span>
+                    </xsl:for-each>
+                </xsl:variable>
+                
+                    
+                <div class="resource">
+                    <h3 id="{$id}">
+                        <xsl:choose>
+                            <xsl:when test="wadl:doc[@title]"><xsl:value-of select="wadl:doc[@title][1]/@title"/></xsl:when>
+                            <xsl:otherwise>
+                                <xsl:copy-of select="$name"/>
+                                <xsl:for-each select="wadl:method[1]/wadl:request/wadl:param[@style='query']">
+                                    <xsl:choose>
+                                        <xsl:when test="@required='true'">
+                                            <xsl:choose>
+                                                <xsl:when test="preceding-sibling::wadl:param[@style='query']">&amp;</xsl:when>
+                                                <xsl:otherwise>?</xsl:otherwise>
+                                            </xsl:choose>
+                                            <xsl:value-of select="@name"/>
+                                        </xsl:when>
+                                        <xsl:otherwise>
+                                            <span class="optional">
+                                                <xsl:choose>
+                                                    <xsl:when test="preceding-sibling::wadl:param[@style='query']">&amp;</xsl:when>
+                                                    <xsl:otherwise>?</xsl:otherwise>
+                                                </xsl:choose>
+                                                <xsl:value-of select="@name"/>
+                                            </span>
+                                        </xsl:otherwise>
+                                    </xsl:choose>
+                                </xsl:for-each>
+                            </xsl:otherwise>
+                        </xsl:choose>
+                        
+                    </h3>
+                    <xsl:apply-templates select="wadl:doc"/>
+                    <xsl:apply-templates select="." mode="param-group">
+                        <xsl:with-param name="prefix">resource-wide</xsl:with-param>
+                        <xsl:with-param name="style">template</xsl:with-param>
+                    </xsl:apply-templates>
+                    <xsl:apply-templates select="." mode="param-group">                        
+                        <xsl:with-param name="prefix">resource-wide</xsl:with-param>
+                        <xsl:with-param name="style">matrix</xsl:with-param>
+                    </xsl:apply-templates>                    
+                    <h6>Methods</h6>
+                    <div class="methods">
+                        <xsl:apply-templates select="wadl:method"/>
+                    </div>
+                </div>
+                <xsl:apply-templates select="wadl:resource" mode="list">
+                    <xsl:with-param name="context" select="$name"/>
+                </xsl:apply-templates>                
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+            
+    <xsl:template match="wadl:method">
+        <xsl:variable name="id"><xsl:call-template name="get-id"/></xsl:variable>
+        <div class="method">
+            <h4 id="{$id}"><xsl:value-of select="@name"/></h4>
+            <xsl:apply-templates select="wadl:doc"/>                
+            <xsl:apply-templates select="wadl:request"/>
+            <xsl:apply-templates select="wadl:response"/>
+        </div>
+    </xsl:template>
+
+    <xsl:template match="wadl:request">
+        <xsl:apply-templates select="." mode="param-group">
+            <xsl:with-param name="prefix">request</xsl:with-param>
+            <xsl:with-param name="style">query</xsl:with-param>
+        </xsl:apply-templates>
+        <xsl:apply-templates select="." mode="param-group">
+            <xsl:with-param name="prefix">request</xsl:with-param>
+            <xsl:with-param name="style">header</xsl:with-param>
+        </xsl:apply-templates> 
+        <xsl:if test="wadl:representation">
+            <p><em>acceptable request representations:</em></p>
+            <ul>
+                <xsl:apply-templates select="wadl:representation"/>
+            </ul>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template match="wadl:response">
+        <xsl:apply-templates select="." mode="param-group">
+            <xsl:with-param name="prefix">response</xsl:with-param>
+            <xsl:with-param name="style">header</xsl:with-param>
+        </xsl:apply-templates> 
+        <xsl:if test="wadl:representation">
+            <p><em>available response representations:</em></p>
+            <ul>
+                <xsl:apply-templates select="wadl:representation"/>
+            </ul>
+        </xsl:if>
+        <xsl:if test="wadl:fault">
+            <p><em>potential faults:</em></p>
+            <ul>
+                <xsl:apply-templates select="wadl:fault"/>
+            </ul>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template match="wadl:representation|wadl:fault">
+        <xsl:variable name="id"><xsl:call-template name="get-id"/></xsl:variable>
+        <li>
+            <a href="#{$id}">
+                <xsl:call-template name="representation-name"/>
+            </a>
+        </li>
+    </xsl:template>    
+    
+    <xsl:template match="wadl:representation|wadl:fault" mode="list">
+        <xsl:variable name="id"><xsl:call-template name="get-id"/></xsl:variable>
+        <xsl:variable name="href" select="@id"/>
+        <xsl:variable name="expanded-name">
+            <xsl:call-template name="expand-qname">
+                <xsl:with-param select="@element" name="qname"/>
+            </xsl:call-template>
+        </xsl:variable>
+        <xsl:choose>
+            <xsl:when test="preceding::wadl:*[@id=$href]"/>
+            <xsl:otherwise>
+                <h3 id="{$id}">
+                    <xsl:call-template name="representation-name"/>
+                </h3>
+                <xsl:apply-templates select="wadl:doc"/>
+                <xsl:if test="@element or wadl:param">
+                    <div class="representation">
+                        <xsl:if test="@element">
+                            <h6>XML Schema</h6>
+                            <xsl:call-template name="get-element">
+                                <xsl:with-param name="context" select="."/>
+                                <xsl:with-param name="qname" select="@element"/>
+                            </xsl:call-template>
+                        </xsl:if>        
+                        <xsl:apply-templates select="." mode="param-group">
+                            <xsl:with-param name="style">plain</xsl:with-param>
+                        </xsl:apply-templates>
+                        <xsl:apply-templates select="." mode="param-group">
+                            <xsl:with-param name="style">header</xsl:with-param>
+                        </xsl:apply-templates>                         
+                    </div>
+                </xsl:if>                
+            </xsl:otherwise>
+        </xsl:choose>        
+    </xsl:template>
+    
+    <xsl:template match="wadl:*" mode="param-group">
+        <xsl:param name="style"/>
+        <xsl:param name="prefix"></xsl:param>
+        <xsl:if test="ancestor-or-self::wadl:*/wadl:param[@style=$style]">
+        <h6><xsl:value-of select="$prefix"/><xsl:text> </xsl:text><xsl:value-of select="$style"/> parameters</h6>
+        <table>
+            <tr>
+                <th>parameter</th>
+                <th>value</th>
+                <th>description</th>
+           </tr>
+            <xsl:apply-templates select="ancestor-or-self::wadl:*/wadl:param[@style=$style]"/>
+        </table>
+        </xsl:if>        
+    </xsl:template>
+    
+    <xsl:template match="wadl:param">
+        <tr>
+            <td>
+                <p><strong><xsl:value-of select="@name"/></strong></p>
+            </td>
+            <td>
+                <p>
+                <em><xsl:call-template name="link-qname"><xsl:with-param name="qname" select="@type"/></xsl:call-template></em>
+                    <xsl:if test="@required='true'"> <small> (required)</small></xsl:if>
+                    <xsl:if test="@repeating='true'"> <small> (repeating)</small></xsl:if>            
+                </p>
+                <xsl:choose>
+                    <xsl:when test="wadl:option">
+                        <p><em>One of:</em></p>
+                        <ul>
+                            <xsl:apply-templates select="wadl:option"/>
+                        </ul>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:if test="@default"><p>Default: <tt><xsl:value-of select="@default"/></tt></p></xsl:if>
+                        <xsl:if test="@fixed"><p>Fixed: <tt><xsl:value-of select="@fixed"/></tt></p></xsl:if>
+                    </xsl:otherwise>
+                </xsl:choose>                        
+            </td>
+            <td>
+                <xsl:apply-templates select="wadl:doc"/>
+                <xsl:if test="wadl:option[wadl:doc]">
+                    <dl>
+                        <xsl:apply-templates select="wadl:option" mode="option-doc"/>
+                    </dl>
+                </xsl:if>
+                <xsl:if test="@path">
+                    <ul>
+                        <li>XPath to value: <tt><xsl:value-of select="@path"/></tt></li>
+                        <xsl:apply-templates select="wadl:link"/>
+                    </ul>
+                </xsl:if>
+            </td>
+        </tr>                
+    </xsl:template>
+
+    <xsl:template match="wadl:link">
+        <li>
+            Link: <a href="#{@resource_type}"><xsl:value-of select="@rel"/></a>            
+        </li>
+    </xsl:template>
+
+    <xsl:template match="wadl:option">
+        <li>
+            <tt><xsl:value-of select="@value"/></tt>
+            <xsl:if test="ancestor::wadl:param[1]/@default=@value"> <small> (default)</small></xsl:if>
+        </li>
+    </xsl:template>
+
+    <xsl:template match="wadl:option" mode="option-doc">
+            <dt>
+                <tt><xsl:value-of select="@value"/></tt>
+                <xsl:if test="ancestor::wadl:param[1]/@default=@value"> <small> (default)</small></xsl:if>
+            </dt>
+            <dd>
+                <xsl:apply-templates select="wadl:doc"/>
+            </dd>
+    </xsl:template>    
+
+    <xsl:template match="wadl:doc">
+        <xsl:param name="inline">0</xsl:param>
+        <!-- skip WADL elements -->
+        <xsl:choose>
+            <xsl:when test="node()[1]=text() and $inline=0">
+                <p>
+                    <xsl:apply-templates select="node()" mode="copy"/>
+                </p>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:apply-templates select="node()" mode="copy"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+    
+    <!-- utilities -->
+
+    <xsl:template name="get-id">
+        <xsl:choose>
+            <xsl:when test="@id"><xsl:value-of select="@id"/></xsl:when>
+            <xsl:otherwise><xsl:value-of select="generate-id()"/></xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="get-namespace-uri">
+        <xsl:param name="context" select="."/>
+        <xsl:param name="qname"/>
+        <xsl:variable name="prefix" select="substring-before($qname,':')"/>
+        <xsl:variable name="qname-ns-uri" select="$context/namespace::*[name()=$prefix]"/>
+        <!-- nasty hack to get around libxsl's refusal to copy all namespace nodes when pushing nodesets around -->
+        <xsl:choose>
+            <xsl:when test="$qname-ns-uri">
+                <xsl:value-of select="$qname-ns-uri"/>                
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:value-of select="$resources/*[1]/attribute::*[namespace-uri()='urn:namespace' and local-name()=$prefix]"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="get-element">
+        <xsl:param name="context" select="."/>
+        <xsl:param name="qname"/>
+        <xsl:variable name="ns-uri">
+            <xsl:call-template name="get-namespace-uri">
+                <xsl:with-param name="context" select="$context"/>
+                <xsl:with-param name="qname" select="$qname"/>
+            </xsl:call-template>
+        </xsl:variable>
+        <xsl:variable name="localname" select="substring-after($qname, ':')"/>
+        <xsl:variable name="definition" select="$grammars/descendant::xs:element[@name=$localname][ancestor-or-self::*[@targetNamespace=$ns-uri]]"/>
+        <xsl:variable name='source' select="$definition/ancestor-or-self::wadl:include[1]/@href"/>
+        <p><em>Source: <a href="{$source}"><xsl:value-of select="$source"/></a></em></p>
+        <pre><xsl:apply-templates select="$definition" mode="encode"/></pre>
+    </xsl:template>
+
+    <xsl:template name="link-qname">
+        <xsl:param name="context" select="."/>
+        <xsl:param name="qname"/>
+        <xsl:variable name="ns-uri">
+            <xsl:call-template name="get-namespace-uri">
+                <xsl:with-param name="context" select="$context"/>
+                <xsl:with-param name="qname" select="$qname"/>
+            </xsl:call-template>
+        </xsl:variable>
+        <xsl:variable name="localname" select="substring-after($qname, ':')"/>
+        <xsl:choose>
+            <xsl:when test="$ns-uri='http://www.w3.org/2001/XMLSchema'">
+                <a href="http://www.w3.org/TR/xmlschema-2/#{$localname}"><xsl:value-of select="$localname"/></a>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:variable name="definition" select="$grammars/descendant::xs:*[@name=$localname][ancestor-or-self::*[@targetNamespace=$ns-uri]]"/>                
+                <a href="{$definition/ancestor-or-self::wadl:include[1]/@href}" title="{$definition/descendant::xs:documentation/descendant::text()}"><xsl:value-of select="$localname"/></a>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="expand-qname">
+        <xsl:param name="context" select="."/>
+        <xsl:param name="qname"/>
+        <xsl:variable name="ns-uri">
+            <xsl:call-template name="get-namespace-uri">
+                <xsl:with-param name="context" select="$context"/>
+                <xsl:with-param name="qname" select="$qname"/>
+            </xsl:call-template>
+        </xsl:variable>
+        <xsl:text>{</xsl:text>
+        <xsl:value-of select="$ns-uri"/>
+        <xsl:text>} </xsl:text> 
+        <xsl:value-of select="substring-after($qname, ':')"/>
+    </xsl:template>
+        
+    
+    <xsl:template name="representation-name">
+        <xsl:variable name="expanded-name">
+            <xsl:call-template name="expand-qname">
+                <xsl:with-param select="@element" name="qname"/>
+            </xsl:call-template>
+        </xsl:variable>
+        <xsl:choose>
+            <xsl:when test="wadl:doc[@title]">
+                <xsl:value-of select="wadl:doc[@title][1]/@title"/>
+                <xsl:if test="@status or @mediaType or @element"> (</xsl:if>
+                <xsl:if test="@status">Status Code </xsl:if><xsl:value-of select="@status"/>
+                <xsl:if test="@status and @mediaType"> - </xsl:if>
+                <xsl:value-of select="@mediaType"/>
+                <xsl:if test="(@status or @mediaType) and @element"> - </xsl:if>
+                <xsl:if test="@element">
+                    <abbr title="{$expanded-name}"><xsl:value-of select="@element"/></abbr>
+                </xsl:if>
+                <xsl:if test="@status or @mediaType or @element">)</xsl:if>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:if test="@status">Status Code </xsl:if><xsl:value-of select="@status"/>
+                <xsl:if test="@status and @mediaType"> - </xsl:if>
+                <xsl:value-of select="@mediaType"/>
+                <xsl:if test="@element"> (</xsl:if>
+                <abbr title="{$expanded-name}"><xsl:value-of select="@element"/></abbr>
+                <xsl:if test="@element">)</xsl:if>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>                
+        
+    <!-- entity-encode markup for display -->
+
+    <xsl:template match="*" mode="encode">
+        <xsl:text>&lt;</xsl:text>
+        <xsl:value-of select="name()"/><xsl:apply-templates select="attribute::*" mode="encode"/>
+        <xsl:choose>
+            <xsl:when test="*|text()">
+                <xsl:text>&gt;</xsl:text>
+                <xsl:apply-templates select="*|text()" mode="encode" xml:space="preserve"/>
+                <xsl:text>&lt;/</xsl:text><xsl:value-of select="name()"/><xsl:text>&gt;</xsl:text>                
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:text>/&gt;</xsl:text>
+            </xsl:otherwise>
+        </xsl:choose>    
+    </xsl:template>            
+    
+    <xsl:template match="@*" mode="encode">
+        <xsl:text> </xsl:text><xsl:value-of select="name()"/><xsl:text>="</xsl:text><xsl:value-of select="."/><xsl:text>"</xsl:text>
+    </xsl:template>    
+    
+    <xsl:template match="text()" mode="encode">
+        <xsl:value-of select="." xml:space="preserve"/>
+    </xsl:template>    
+
+    <!-- copy HTML for display -->
+    
+    <xsl:template match="html:*" mode="copy">
+        <!-- remove the prefix on HTML elements -->
+        <xsl:element name="{local-name()}">
+            <xsl:for-each select="@*">
+                <xsl:attribute name="{local-name()}"><xsl:value-of select="."/></xsl:attribute>
+            </xsl:for-each>
+            <xsl:apply-templates select="node()" mode="copy"/>
+        </xsl:element>
+    </xsl:template>
+    
+    <xsl:template match="@*|node()[namespace-uri()!='http://www.w3.org/1999/xhtml']" mode="copy">
+        <!-- everything else goes straight through -->
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()" mode="copy"/>
+        </xsl:copy>
+    </xsl:template>    
+
+</xsl:stylesheet>