You're sort of exaggerating the boilerplate there; a more idiomatic, complete template might be:
<xsl:variable name="nav-menu-items">
<item href="foo.xhtml"><strong>Foo</strong> Page</item>
<item href="bar.xhtml"><em>Bar</em> Page</item>
<item href="baz.xhtml">Baz <span>Page</span></item>
</xsl:variable>
<xsl:template match="nav-menu">
<nav>
<ul>
<xsl:apply-templates select="$nav-menu-items/item">
<xsl:with-param name="current" select="@current-page"/>
</xsl:apply-templates>
</ul>
</nav>
</xsl:template>
<xsl:template match="item">
<xsl:param name="current"/>
<li>
<xsl:choose>
<xsl:when test="@href=$current">
<a class="selected"><xsl:apply-templates/></a>
</xsl:when>
<xsl:otherwise>
<a href="{@href}"><xsl:apply-templates/></a>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:template>
One nice thing about XSLT is that if you start with a passthrough template:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
You have basically your entire "framework" with no need to figure out how to set up a build environment because there is no build environment; it's just baked into the browser. Apparently in XSLT 3.0, the passthrough template is shortened to just `<xsl:mode on-no-match="shallow-copy"/>`. In XSLT 2.0+ you could also check against `base-uri(/)` instead of needing to pass in the current page with `<nav-menu current-page="foo.xhtml"/> and there's no `param` and `with-param` stuff needed. In modern XSLT 3.0, it should be able to be something more straightforward like:
<xsl:mode on-no-match="shallow-copy"/>
<xsl:variable name="menu-items">
<item href="foo.xhtml"><strong>Foo</strong> Page</item>
<item href="bar.xhtml"><em>Bar</em> Page</item>
<item href="baz.xhtml">Baz <span>Page</span></item>
</xsl:variable>
<xsl:template match="nav-menu">
<nav>
<ul>
<xsl:apply-templates select="$menu-items/item"/>
</ul>
</nav>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:variable name="current-page" select="tokenize(base-uri(/),'/')[last()]"/>
<a href="{if (@href = $current-page) then '' else @href}"
class="{if (@href = $current-page) then 'selected' else ''}">
<xsl:apply-templates/>
</a>
</li>
</xsl:template>
The other nice thing is that it's something that's easy to grow into. If you
don't want to get fancy with your menu, you can just do:
<xsl:template match="nav-menu">
<nav>
<ul>
<li><a href="foo.xhtml">Foo</a></li>
<li><a href="bar.xhtml">Bar</a></li>
<li><a href="baz.xhtml">Baz</a></li>
</ul>
</nav>
</xsl:template>
And now you have a `<nav-menu/>` component that you can add to any page. So to the extent that you're using it to create simple website templates but you're not a "web dev", it works really well for people that don't want to go through all of the hoops that professional programmers deal with. Asking people to figure out react to make a static website is absurd.