Firstly, <xsl:for-each select="."> is a null operation. You can simply remove it - but try to understand why, because the fact that you wrote it suggests you have some misunderstanding about the way templates work.
In this code
<xsl:choose>
<xsl:when test="title">
<xsl:apply-templates select="title" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates name="level" />
</xsl:otherwise>
</xsl:choose>
I assume the name="level" should be select="level" (it won't even compile as written). With this change, it's saying "if there is a title child, process the title child, otherwise process the level child". Well there's nothing wrong with that, but I suspect that when an element has a title child and a level child then you actually want to process both. Which you can do simply by calling <xsl:apply-templates/> - no xsl:choose needed, no select attribute needed.
When your input contains a level as a direct child of another level, the simple approach will output a ul as a direct child of a ul, which isn't correct HTML - there needs to be an intervening li. One way to achieve this (in XSLT 2.0) is to have a template
<xsl:template match="level/level">
<li>
<xsl:next-match/>
</li>
</xsl:template>
which generates the li element and then implicitly invokes the match="level" template. The next-match instruction isn't available in 1.0; you could achieve it by giving the match="level" template a name and invoking it using call-template.
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference