Relative URLs for XSLT Page Templates

I’ve been wondering how best to create HTML output with links using relative URLs. There are a number of discussions about how best to redirect internal links in XML content:

Absolute URLs for XML content

But how can I create relative URLs instead? I posted this question on the Symphony CMS forum.

Relative URLs for XSLT Page Templates

So, in Symphony CMS, I want to produce URLs that look like this:

<ul class="nav">
    <li><a href="../">Home</a></li>
    <li><a href="../about/">About</a></li>
    <li><a href="../work/">Work</a></li>
    <li><a href="../contact/">Contact</a></li>
</ul>

rather than this:

<ul class="nav">
    <li><a href="http://example.com/">Home</a></li>
    <li><a href="http://example.com/about/">About</a></li>
    <li><a href="http://example.com/work/">Work</a></li>
    <li><a href="http://example.com/contact/">Contact</a></li>
</ul>

What I have yet to see is how to create relative URL structures for a site. For example, I could have a page that has the following URL parameters:

a/b/c/d/e/f

My first thought would be to determine what the currently selected level is, then set the relative root string:

<xsl:param name="level">
    <xsl:choose>
        <xsl:when test="$current-page = 'home'">0</xsl:when>
        <xsl:when test="$f">6</xsl:when>
        <xsl:when test="$e">5</xsl:when>
        <xsl:when test="$d">4</xsl:when>
        <xsl:when test="$c">3</xsl:when>
        <xsl:when test="$b">2</xsl:when>
        <xsl:when test="$a">1</xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
</xsl:param>
<xsl:param name="root-rel">
    <xsl:choose>
        <xsl:when test="$level = 0">./</xsl:when>
        <xsl:when test="$level = 1">../</xsl:when>
        <xsl:when test="$level = 2">../../</xsl:when>
        <xsl:when test="$level = 3">../../../</xsl:when>
        <xsl:when test="$level = 4">../../../../</xsl:when>
        <xsl:when test="$level = 5">../../../../../</xsl:when>
        <xsl:when test="$level = 6">../../../../../../</xsl:when>
    </xsl:choose>
</xsl:param>

Or, I could skip the separate test for the current level and do both with a single parameter:

<xsl:param name="root-rel">
    <xsl:choose>
        <xsl:when test="$f">../../../../../../../</xsl:when>
        <xsl:when test="$e">../../../../../../</xsl:when>
        <xsl:when test="$d">../../../../../</xsl:when>
        <xsl:when test="$c">../../../../</xsl:when>
        <xsl:when test="$b">../../../</xsl:when>
        <xsl:when test="$a">../../</xsl:when>
        <xsl:when test="$current-page != 'home'">../</xsl:when>
        <xsl:otherwise>./</xsl:otherwise>
    </xsl:choose>
</xsl:param>

When packaging the files for the Fluid Grid System, I ended up building the pages in Symphony, but had to edit each individual file, using a search-and-replace function in a text editor, to produce the HTML demo with relative URLs. This is less than ideal.

My solution lacks some flexibility, though, since, for every page that uses a different set of URL parameters, this template needs to change to test for the correct sequence of URL parameters. This would require a different master template for every page where the URL parameters are different, negating the usefulness of a master template. Is there a more flexible way to do this? Perhaps, the answer for this scenario is to always use the same sequence and names for URL parameters and be sure that the data source filtering references these parameters.

Journal
Technology symphony cms xslt 2009-07-14 Yes