This is a good use case for a schema-aware stylesheet.
Expanding on my previous reply, the following stylesheet:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xsi:schemaLocation="schema-for-xslt20.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="xsi">
<xsl:output method="xml" indent="yes"/>
<xsl:import-schema namespace="http://www.w3.org/1999/XSL/Transform"
schema-location="schema-for-xslt20.xsd"/>
<xsl:template match="/">
<xsl:if test="not(* instance of schema-element(xsl:transform))">
<xsl:message terminate="yes">Input document must be a schema-validated
stylesheet</xsl:message>
</xsl:if>
<expressions>
<xsl:apply-templates/>
</expressions>
</xsl:template>
<xsl:template match="xsl:*" priority="2">
<!-- match XSLT elements -->
<xsl:apply-templates select="attribute(*, xsl:expression) except
attribute(*, xsl:pattern)"/>
<xsl:apply-templates select="attribute(*, xsl:avt)[matches(., '\{[^{]')]"
/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*" priority="1">
<!-- match literal result elements -->
<xsl:apply-templates select="@* except @xsl:*" />
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="@*">
<expression attribute="{name()}"><xsl:value-of select="."/></expression>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
when run against itself, produces the output:
<?xml version="1.0" encoding="UTF-8"?>
<expressions>
<expression attribute="test">not(* instance of
schema-element(xsl:transform))</expression>
<expression attribute="select">child::node()</expression>
<expression attribute="select">attribute(*, xsl:expression) except
attribute(*, xsl:pattern)</expression>
<expression attribute="select">attribute(*, xsl:avt)[matches(.,
'\{[^{]')]</expression>
<expression attribute="select">child::node()</expression>
<expression attribute="select">@* except @xsl:*</expression>
<expression attribute="select">child::node()</expression>
<expression attribute="attribute">{name()}</expression>
<expression attribute="select">.</expression>
</expressions>
(The "child::node()" entries appear because the schema for XSLT 2.0 expands
the default value of the select attribute of xsl:apply-templates.)
To run this, download Saxon-SA 8.0 from www.saxonica.com (you will need to
apply for an evaluation license) and run it using the command:
java com.saxonica.Transform -val test.xsl test.xsl
You can also, of course, run it against any other stylesheet, provided that
the input stylesheet is validated against the schema for stylesheets. In my
example I added an xsi:schemaLocation attribute to achieve this, but this
could be avoided if you run the transformation from the Java API rather than
from the command line.
Since this is a student exercise, I will leave you to do the job of
explaining how this works.
Michael Kay