[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Truncating output of a node

Subject: Re: Truncating output of a node
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 19 Apr 2001 23:17:40 +0100
xsl move to next node
Hi Jim,

> I guess another possibility it to output n characters and add '...'
> at the end to create the summary. Is that any easier?

I can just tell everyone's dying for a patented Jeni solution to this
problem. So here's my approach - step through the nodes one by one,
keeping track of the number of sentences that have been output so far
(as Mike suggested). Be careful, though - text nodes might hold more
than one sentence, so you need to have some recursion over the string
in there as well.

So have one template for text nodes:

<xsl:template match="text()" name="text">
   <!-- $sentences holds the number of sentences covered so far -->
   <xsl:param name="sentences" select="0" />
   <!-- $text holds the text of the text node (or portion of a text
        node when this template is called recursively -->
   <xsl:param name="text" select="." />
   <!-- $next holds the next node to move on to -->
   <xsl:param name="next" select="following-sibling::*[1]" />
      <!-- if this text contains a sentence delimiter... -->
      <xsl:when test="contains($text, '. ')">
         <!-- ... finish the sentence ... -->
         <xsl:value-of select="substring-before($text, '. ')" />
         <xsl:text>. </xsl:text>
         <!-- ... and if we've output less than 2 sentences before
              (i.e. we've not just finished the third) ... -->
         <xsl:if test="$sentences &lt; 2">
            <!-- ... call the template on the rest of the string ...
            <xsl:call-template name="text">
               <!-- ... adding one to the sentences count -->
               <xsl:with-param name="sentences" select="$sentences + 1" />
               <!-- ... passing the rest of the text node -->
               <xsl:with-param name="text"
                               select="substring-after($text, '. ')" />
               <!-- ... and keeping the same next node -->
               <xsl:with-param name="next" select="$next" />
         <!-- ... otherwise just give the value of the string ... -->
         <xsl:value-of select="$text" />
         <!-- ... and apply templates to the following span element,
              keeping the number of sentences the same -->
         <xsl:apply-templates select="$next">
            <xsl:with-param name="sentences" select="$sentences" />

Have another template for span elements, which can be a lot simpler,
just basically applies templates to the next node, passing through the
same count - this takes advantage of the fact that sentences never end
within span elements:

<xsl:template match="span">
   <xsl:param name="sentences" select="0" />
   <xsl:copy-of select="." />
   <xsl:apply-templates select="following-sibling::node()[1]">
      <xsl:with-param name="sentences" select="$sentences" />

Then you can start the process by just applying templates to the first
node under the summary:

<xsl:template match="summary">
   <xsl:apply-templates select="node()[1]" />

I hope that helps,


Jeni Tennison

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Current Thread


Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
First Name
Last Name
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.