Search

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

Relative URLs for XSLT Page Templates

So, 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.

Why would you want to do that?

Yeah, I had the same question. What’s the use-case?

That’s a lot of logic to save a few extra bytes being sent to the client.

Since the variables in a URL are managed by Symphony (or any CMS for that matter), there’s really no reason to use relative URLs.

Because I’m creating HTML output that can be distributed in a directory and archived as a ZIP archive. If the directory is installed on a web server, the pages are still accessible at any level in the directory hierarchy because they use relative URLs. These pages would break if they used absolute URLs. For example. It’s still a bit of a manual process, because I am copying and pasting HTML. (It would be cool to have an extension that writes the files as HTML in the proper directory structure.) But, it’s still better than copying and searching-and-replacing absolute URLs with relative URLs.

This is an edge case, but I find I need this when the goal is to distribute HTML and CSS without requiring Symphony to view a design. I prefer to build my prototypes in Symphony, because of its flexibility to produce whatever markup I like and ensure that it is valid. The end product is often produced in another CMS (sad to say), so I need an easy way to package the prototypes for distribution.

@bauhouse, That makes sense. I didn’t consider offline distribution when making my statement.

Have you tried using the base tag in the head?

eg:

<base href="{$root}"/>

Then, all your page links automatically get the root url added to them by the browser. I’ve been using it for years without issue, and it is a valid part of the HTML and XHTML specs.

You could also look at using a tool such as Site Sucker to do the relative-ising for you.

@Henry, I haven’t tried that. I’ll give that a shot. Sounds like that would work well if I need absolute URLs.

@Makenosound, that would make things easier to package up the files. That’s what I get for trying to do absolutely everything with Symphony.

@bauhouse: Nice to know that it can at least :p

I’ve used Site Sucker for exactly the purpose you’re talking about and it works perfectly—just need to fiddle with the settings a little. I was sucking down a clients’ legacy ASP site and, apart from ignoring a few file references specified in JavaScript, it made a nice portable version of the site.

@ Henry, thanks I have been referencing base, along with a link to a blogpost with more info, in the mentioned articles, but never got any feedback on wether it would be a good solution

The base element works in some situations, but often you do need the absolute URL. I use the same XSLT to create Articles pages and their associated RSS feeds — the RSS feed needs absolute URLs back to the original site, particularly any relative links inside Markdown-formatted textareas.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details