Посмотрите на этот вопрос здесь
Существует ли элемент имени XSLT?
Вы можете использовать
<xsl:value-of select ="name(.)"/>
или
<xsl:value-of select ="local-name()"/>
для получения имени узла, в зависимости от того, хотите ли вы включить полное префиксное имя или только локальную часть.
Вы должны быть в состоянии собрать их вместе с блоками xsl: for-each, чтобы перебрать первые 3 уровня элементов и сгенерировать искомый HTML.
Примерно так будет работать для фиксированного количества уровней.
<xsl:for-each select="*">
<html>
<head>
<title><xsl:value-of select="local-name()" /></title>
</head>
<body>
<div class="root">
<xsl:for-each select="*">
<div>
<xsl:attribute name="class">
<xsl:value-of select="local-name()" />
</xsl:attribute>
<xsl:for-each select="*">
<b><xsl:value-of select="local-name()" />:</b> <xsl:value-of select="." />
</xsl:for-each>
</div>
</xsl:for-each>
</div>
</body>
</html>
</xsl:for-each>
Более общий подход будет выглядеть примерно так:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes" version="4.0"/>
<xsl:template match="/">
<xsl:for-each select="*">
<html>
<head>
<title><xsl:value-of select="local-name()" /></title>
</head>
<body>
<div class="root">
<xsl:call-template name="recurseElement">
<xsl:with-param name="element" select="." />
</xsl:call-template>
</div>
</body>
</html>
</xsl:for-each>
</xsl:template>
<xsl:template name="recurseElement">
<xsl:param name="element" />
<xsl:for-each select="$element/*">
<xsl:choose>
<xsl:when test="count(child::*)>0">
<div>
<xsl:attribute name="class">
<xsl:value-of select="local-name()" />
</xsl:attribute>
<xsl:call-template name="recurseElement">
<xsl:with-param name="element" select="." />
</xsl:call-template>
</div>
</xsl:when>
<xsl:otherwise>
<b><xsl:value-of select="local-name()" />:</b> <xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>