This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: Truncating output of a node


At 08:20 PM 4/19/01, you wrote:
>I guess another possibility it to output n characters and add '...' at the
>end to create the summary. Is that any easier?

Considerably easier, although what you stipulate about how the "." may be 
good enough , makes the harder problem easier too.

It would be really easy if you didn't care about those embedded <span> 
elements. Then you could just do:

<xsl:variable name="allowable-length" select="100"/>
<!-- let's say 100 characters is a good number -->

<xsl:template match="summary">
   <xsl:value-of select="substring(., 1, $allowable-length)"/>
   <xsl:if test="string-length(.) &gt; $allowable-length">
     <xsl:text>...</xsl:text>
   </xsl:if>
</xsl:template>

But with those embedded <span> elements, things are harder. I'm not going 
to tackle the "break on sentences" problem; we'll go with testing on string 
length.

Maybe something like:

<xsl:variable name="allowable-length" select="100"/>

<xsl:template match="summary">
   <xsl:apply-templates/>
</xsl:template>

<xsl:template name="string-segment">
   <!-- outputs as much of the string as will fit -->
   <xsl:variable name="string-before">
     <xsl:for-each select="$preceding-sibling::*|preceding-sibling::text()">
       <!-- counting only elements and text nodes, not comments or
            processing-instructions -->
       <xsl:value-of select="."/>
     </xsl:for-each>
   </xsl:variable>
   <xsl:variable name="length-before" select="string-length($string-before)"/>
   <xsl:if test="$length-before &lt; $allowable-length">
     <!-- part of this string will fit! we're in business -->
     <xsl:variable name="length-left" select="$allowable-length - 
$length-before"/>
     <xsl:value-of select="substring(., 1, $length-left)"/>
     <xsl:if test="string-length(.) &gt; $length-left">
       <xsl:text>...</xsl:text>
     </xsl:if>
   </xsl:if>
</xsl:template>

<xsl:template match="summary/text()">
   <xsl:call-template name="string-segment"/>
</xsl:template>

<xsl:template match="summary/span">
   <b> <!-- I'm just making all spans <b>; do what you like -->
     <xsl:call-template name="string-segment"/>
   </b>
</xsl:template>

If I'm thinking about this the right way, it'll work as long as you only 
have text nodes and span elements in your summary, and you don't have any 
elements you need to process *inside* the spans, just text nodes.

Note -- untested: sure to be typos and maybe worse. Also -- expect 
performance to be pretty lame....

Hope this helps!
Wendell

======================================================================
Wendell Piez                            mailto:wapiez@mulberrytech.com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
   Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]