p2p.wrox.com Forums

Need to download code?

View our list of code downloads.


Go Back   p2p.wrox.com Forums > XML > XSLT
I forgot my password Register Now
Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.

Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox p2p Programmer to Programmer discussion community. This is a community of more than 40,000 computer programmers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining our free Wrox p2p community you can post your own programming questions and respond to other programmers’ questions. Registered users also don't have to see the ads that are displayed to guests. Registration is fast, simple and absolutely free so please, join today!
Join today and post to win prizes! Post more to increase your chances of being Wrox’s top poster of the month.

Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old July 3rd, 2009, 03:48 AM
Authorized User
Points: 204, Level: 4
Points: 204, Level: 4 Points: 204, Level: 4 Points: 204, Level: 4
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: May 2006
Location: Haarlem, , Netherlands.
Posts: 46
Thanks: 0
Thanked 0 Times in 0 Posts
Default truncate text including tags

My mission is to output a text block in html and truncate the text at around a specific amount of characters. But the text can hold some extra inline tags like anchor tags. Not tables. I only want to count the rendered text not the markup. When I want to truncate the text and put an ellipsis after the text I don't want the tag to be truncated so that I end up with invalid html. Has anybody had this mission before and can help me solving this problem.
For example truncate a text at say around 20 characters. And the xml is "I want to be <a href='#'>truncated</a> here.
The output must be "I want to be <a href='#'>truncat</a>..." in the browser you see : I want to be truncat... . I don't ask for a total code but just a hint how my strategy should look like ( total code is always appreciated :-)

Last edited by rjonk : July 3rd, 2009 at 03:50 AM.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Reddit!
Reply With Quote
  #2 (permalink)  
Old July 3rd, 2009, 05:04 AM
mhkay's Avatar
Wrox Author
Points: 12,642, Level: 48
Points: 12,642, Level: 48 Points: 12,642, Level: 48 Points: 12,642, Level: 48
Activity: 97%
Activity: 97% Activity: 97% Activity: 97%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 3,900
Thanks: 0
Thanked 80 Times in 78 Posts
Default

I can think of two approaches.

(a) this is harder especially if you aren't accustomed to recursive functional programming, but it's probably more efficient: you basically need to program a recursive scan of all the descendants, accumulating the total text length in a parameter as you go, and terminating the recursion when the text length exceeds 20.

(b) alternatively you can use the built-in apply-templates tree walk, and test each text node to see how much text there is in preceding text nodes. This will have O(n^2) performance, but the logic may be simpler.

Either way, I'm afraid it would take me a little longer than the couple of minutes I allow myself when giving free coding advice!
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Reddit!
Reply With Quote
  #3 (permalink)  
Old August 2nd, 2009, 10:02 AM
Authorized User
Points: 204, Level: 4
Points: 204, Level: 4 Points: 204, Level: 4 Points: 204, Level: 4
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: May 2006
Location: Haarlem, , Netherlands.
Posts: 46
Thanks: 0
Thanked 0 Times in 0 Posts
Thumbs up This is my solution that works for me now

Description:
This template truncates the text of the introductie node until a maximum characters are reached. When the text is truncated
an ellipsis is added to the truncated text. When the text is smaller than the maximum no ellipsis is added
at the end of the introductie text a link will be added

Parameters:
* limit (optional) number of characters to limit by. Default 250 characters
* suffix (optional) the suffix character string to use when the text is truncated. Default '...'
* url the url on the 'more' link
Example:
<xsl:apply-templates select="path/to/your/introductie" mode="truncate"/>

Code:
   <xsl:template match="art:introductie" mode="truncateTree">
        <xsl:param name="limit" select="250"/>
        <xsl:param name="suffix" select="'...'"/>
        <xsl:param name="url"/>
        
        <!-- copy introduction node to redesign the content and later process this copy-->
        <xsl:variable name="truncatedNode">
            <xsl:copy-of select="*"/>
        </xsl:variable>
        
        <!-- create new truncated node -->
        <xsl:variable name="truncatedNodeTree">
            <xsl:apply-templates mode="truncate" select="$truncatedNode/*">
                <xsl:with-param name="limit" select="$limit"/>
                <xsl:with-param name="suffix" select="$suffix"/>
                <xsl:with-param name="url" select="$url"/>
            </xsl:apply-templates>
            
        </xsl:variable>
        
        <!--process new created truncated introduction tree with the general xslt-->
        <xsl:apply-templates select="$truncatedNodeTree/*"/>
        
    </xsl:template>
    
    <!-- process each node -->
    <xsl:template match="*" mode="truncate">
        <xsl:param name="limit"/>
        <xsl:param name="suffix"/>
        <xsl:param name="url"/>
       
        <xsl:variable name="preceding-strings">
            <xsl:copy-of select="preceding::text()"/>
        </xsl:variable>
        
        <!-- precedingchar: number of characters up to the current node -->
        <xsl:variable name="precedingchar" select="string-length(normalize-space($preceding-strings))"/>
        
        <xsl:if test="$precedingchar &lt; $limit">
            <xsl:element name="{name()}">
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates mode="truncate">
                    <xsl:with-param name="limit" select="$limit"/>
                    <xsl:with-param name="suffix" select="$suffix"/>
                </xsl:apply-templates>
                <!-- only add link at end of first element this is the first node inside introductie-->
                <xsl:if test="position()=1">
                    <xsl:text> </xsl:text><link class="actionLink" xlink:href="{$url}" xlink:title="More">More</link>
                </xsl:if>
            </xsl:element>
        </xsl:if>
    </xsl:template>
    
    <!-- process each text node -->
    <xsl:template match="text()" mode="truncate">
        <xsl:param name="limit"/>
        <xsl:param name="suffix"/>
        <xsl:variable name="preceding-strings">
            <xsl:copy-of select="preceding::text()"/>
        </xsl:variable>
        
        <!-- precedingchar: number of characters up to the current node -->
        <xsl:variable name="precedingchar" select="string-length(normalize-space($preceding-strings))"/>
        
        <xsl:if test="$precedingchar &lt; $limit">
           <!-- totalchar: number of characters including current node -->
           <xsl:variable name="totalchar" select="$precedingchar + string-length(.)"/>
           
           <xsl:choose>
               <xsl:when test="$totalchar &gt; $limit ">
                   <!-- truncate until limit reached -->
                   <xsl:value-of select="substring(., 1, ($limit - $precedingchar))"/>
                   <xsl:value-of select="$suffix"/>
                   <xsl:text> </xsl:text>
               </xsl:when>
               <xsl:otherwise>
                   <!-- dont have to truncate text -->
                   <xsl:value-of select="."/>
               </xsl:otherwise>
           </xsl:choose>
        </xsl:if>
        
    </xsl:template>
this is an example xml
Code:
<Article xml:lang="nl" xmlns="http://article/version_1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
	<titel>Test truncation</titel>
	<article.info>
		<date>9-7-2009</date>
		<introductie>
			<alinea>This is the introduction text
				<special>This must be created bold</special>
				This is some text node too. <special >Make this also bold please</special> Again a  text node. For more information please visit:
				<special>www.frontendplace.nl</special>
				This is the last textnode.
			</alinea>
		</introductie>
	</article.info>
</Article>
and this is the template inside the calling xslt
Code:
<xsl:template name="summary">
		<xsl:param name="url" select="'.'"/>
		<xsl:param name="truncate" select="200"/>
		<h3>
			<a href="{$url}">
				<xsl:value-of select="art:titel"/>
			</a>
		</h3>
		<div class="introductie">
			<xsl:apply-templates mode="truncateTree" select="art:artikel.info/art:introductie">
				<xsl:with-param name="limit" select="$truncate"/>
				<xsl:with-param name="suffix" select="'...'"/>
				<xsl:with-param name="url" select="$url"/>
			</xsl:apply-templates>
		</div>
	</xsl:template>
	<xsl:template match="art:special">
		<strong><xsl:apply-templates/></strong>
	</xsl:template>
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Reddit!
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
how to find text within range of two tags dipsut XSLT 3 May 25th, 2007 05:27 PM
Tags as text in XML elements janise XML 16 January 2nd, 2007 06:45 AM
Display full value in text box, including "" BurhanKhan ASP Forms 3 July 18th, 2004 04:59 PM
Including a text file mahulda ASP.NET 1.0 and 1.1 Basics 2 June 27th, 2004 11:21 AM
Extracting text between tags aware Classic ASP Professional 4 December 24th, 2003 04:25 AM



All times are GMT -4. The time now is 01:22 PM.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
© 2008 Wiley Publishing, Inc