I'm not an XML/XSL master by any means, but I'll try and help here. The source
fragment provided doesn't match the output provided and I'm not sure how you
declare your bullet key. This is what I do see. You explicitly place the <ul>
tag everytime because it is embedded in your <li> tag from this code here:
<xsl:for-each-group select="$bullet[not(@level='0')]"
group-starting-with="*[xs:integer(@level) eq $level]">
<li><xsl:value-of select="normalize-space(.)"/>
<ul>
<xsl:call-template name="process-level">
<xsl:with-param name="bullet" select="current-group() except ."/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:call-template>
</ul>
</li>
</xsl:for-each-group>
It seems the reason your process-level isn't returning any <li> tags is because
there isn't a level 3. What's happening is you are outputting the <ul> before
checking to see whether there is a value. I think what you want to do is check
to see if:
<xsl:if test="@level < following-sibling::bullet[(_at_)level][1]">
<ul>
<xsl:apply-templates/> <-- You'll have to edit this
</ul>
</xsl>
I'm assuming there aren't any empty bullet nodes. I'm also assuming bullets are
listed in order since ther edoesn't seem to be any attribute relating a
descendant bullet to its parent. Hopefully this helps.
-Joe