[xsl] Unexpected result from <a href="...">...</a> in some cases

Subject: [xsl] Unexpected result from <a href="...">...</a> in some cases
From: Quinn Taylor <quinntaylor@xxxxxxx>
Date: Tue, 19 Aug 2008 14:19:26 -0600
I've scanned through the archives, but haven't yet found a solution
for this particular problem. First post to the list, so be
merciful.  :-)

I've created a recursive template (printRecursivePath) to process a
directory path and build up a string of links from the right side so
as to correctly increase the number of "../" elements for parent link.
(I tried using the tokenize() function, but  it's apparently not
supported in my XSLT, and I'd like to keep this portable and minimize
dependencies.) The output is in HTML for a standard webpage.

The problem occurs for path components between the first and the last
component. I'm trying to use an <a href="{$parentPath}">...</a> to
create a link, and it works for the first path element, but not for
any of the restit only prints the label that goes between the opening
and closing tags. I've included commented-out code which demonstrate
that it's processing as expected with the exception of this one
glitch. (I'm a CS grad student, so recursion has become second nature
to me and I'm quite certain the error isn't there. I've debugged this
is oXygen, and all the variables had the expected values.)

I also tried the following alternative, which behaves the same:

	<xsl:element name="a">
		<xsl:attribute name="href">
			<xsl:value-of select="$parentPath"/>
		</xsl:attribute>
		<xsl:text>[root]</xsl:text>
	</xsl:element>

I've been testing my XSL in both Safari 3.1.2 in OS X Leopard and
TextXSLT (http://www.entropy.ch/software/macosx/#testxslt) using both
Sablotron and libxslt (can't find documentation of which versions it
uses, but the latest release is from 2005). This is just the XSL file;
since I'm calling the template from <xsl:template match="*"> it will
ignore the contents of XML fed to it.

There may be a better way to do what I'm doing, and I'm open to
suggestions, although my primary concern is being able to reliably
create a link tag. However, I do wonder about what symbol I should use
to designate where the parent path beginsright now I'm using $, but
this would break if any of the path components contain that symbol.
Any thoughts are welcome.

Thanks in advance,
- Quinn Taylor




<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0"> <xsl:output method="html"/>

	<xsl:template match="*">
		<xsl:call-template name="printRecursivePath">
			<xsl:with-param name="text">/path/to/resource</xsl:with-param>
		</xsl:call-template>
	</xsl:template>

	<!-- Split path components at '/', add parent directory links -->
	<xsl:template name="printRecursivePath">
		<xsl:param name="text"/>
		<xsl:variable name="head" select="substring-before($text,'/')"/>
		<xsl:variable name="tail" select="substring-after($text,'/')"/>
		<xsl:if test="$tail">
			<!-- Make a tail-recursive call and store the text result in a
variable -->
			<xsl:variable name="recursiveResult">
				<xsl:call-template name="printRecursivePath">
					<xsl:with-param name="text" select="$tail"/>
				</xsl:call-template>
			</xsl:variable>
			<!-- Split the parent path from the text generated so far -->
			<xsl:variable name="generatedText" select="substring-
before($recursiveResult,'$')"/>
			<xsl:variable name="parentPath" select="substring-
after($recursiveResult,'$')"/>

			<xsl:if test="$head">
				<xsl:text> / </xsl:text>
			 	<a href="{$parentPath}"><xsl:value-of select="$head"/></a>
<!--
				<xsl:text>&lt;</xsl:text>
				<xsl:value-of select="$parentPath"/>
				<xsl:value-of select="$head"/>
				<xsl:text>&gt;</xsl:text>
-->
				<!-- Include the processed tail of the path components -->
				<xsl:value-of select="$generatedText"/>
				<!-- Include the recursively-returned parent path at the end -->
				<xsl:text>$../</xsl:text>
				<xsl:value-of select="$parentPath"/>
			</xsl:if>
			<!-- Prepend a link for the implicit path root -->
			<xsl:if test="not($head)">
			 	<a href="{$parentPath}">[root]</a>
				<!-- Include the processed text of all path components -->
				<xsl:value-of select="$generatedText"/>
			</xsl:if>
		</xsl:if>
		<!-- Recursive base case: end of the path -->
		<xsl:if test="not($tail)">
			<xsl:text> / </xsl:text>
			<xsl:value-of select="$text"/>
			<!-- Include the first value for $parentPath -->
			<xsl:text>$../</xsl:text>
		</xsl:if>
	</xsl:template>

</xsl:stylesheet>

Current Thread