Link to home
Start Free TrialLog in
Avatar of Kreuz Nacher
Kreuz Nacher

asked on

XSLT Title Character Truncation and xsl:choose Option

My XSLT pulls in titles that need to be truncated to 100 characters.

I can get this to work but it sometimes cuts words off.  I would like to have my XSLT take the last full word before the character limit and then add a " ..." to indicate that it's been truncated.  

Can someone help me out with this code?  


This works, but clips words
<div class="item link-item" ><ul><li> <a href="{ddwrt:EnsureAllowedProtocol(string(link))}" target="_blank"><xsl:value-of select="substring(title, 1, 140)"/></a></li></ul>

Open in new window


Trying to keep last word and then add ... when it exceeds length
<div class="item link-item" ><ul><li><a href="{ddwrt:EnsureAllowedProtocol(string(link))}" target="_blank">
<xsl:choose>
	<xsl:when test="string-length(title) > 100">
		<xsl:value-of select="substring(title, 1, 96)" />
		<xsl:text> ...</xsl:text>
	</xsl:when>
	<xsl:otherwise>
		<xsl:value-of select="title" />
	</xsl:otherwise>
</xsl:choose>
</a></li></ul>

Open in new window

Avatar of Kreuz Nacher
Kreuz Nacher

ASKER

To further clarify, This all works in both cases, but the second option that adds the " ..." isn't truncating the last word, it is only truncating characters, so some words are cut off.
Avatar of Gertone (Geert Bormans)
Hi, I think I understand what you need.
The best way to handle such a case in XSLT is by building up the result string recursively until the pipe is full
(recursion is your friend ;-)

I developed a named template you could use, but it only works if you don't care about the whitespaces such as newline and tab etc
(given the result is html, I don't think you do)
This solution requires the use of normalize-space() which turns every sequence of whitespace into a single space character

    <xsl:template name="truncate-with-tail">
        <xsl:param name="str"/>
        <xsl:param name="remainder"/>
        <xsl:param name="tail" select="' ...'"/>
        <xsl:variable name="first-word" select="substring-before($str, ' ')"/>
        <xsl:choose>
            <xsl:when test="$remainder > string-length($first-word) + string-length($tail)">
                <xsl:value-of select="$first-word"/>
                <xsl:text> </xsl:text>
                <xsl:call-template name="truncate-with-tail">
                    <xsl:with-param name="str" select="normalize-space(substring-after($str, $first-word))"/>
                    <xsl:with-param name="remainder" select="$remainder - 1 - string-length($first-word)"/>
                    <xsl:with-param name="tail" select="$tail"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$tail"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    

Open in new window

Here is how you could call it in your code

<div class="item link-item" ><ul><li><a href="{ddwrt:EnsureAllowedProtocol(string(link))}" target="_blank">
           <xsl:call-template name="truncate-with-tail">
                <xsl:with-param name="str" select="normalize-space(title)"/>
                <xsl:with-param name="remainder" select="100"/>
                <xsl:with-param name="tail" select="' ...'"/>
            </xsl:call-template>
</a></li></ul>

Open in new window

This is working great except for one thing.  If you could be so kind as to "feed" me a little more.  

Every word that has punctuation at the end of it is getting cut off, even if I increase the select attribute from 100 to 500 just to test.  
  • For example:  "Meet me for lunch!" shows up after this transform as "Meet me for ..."
Here is an example.  The XML source is an RSS Feed, and the transform results are shown below.  Character limit is set to 500 currently, so it should include the whole title.

User generated image
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is awesome, exactly what I needed.  I used to code XSL many years ago and am quite rusty, this has been very helpful.  Thank you!