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

Enjoy! (was: Re: Limit the length of transformed

Subject: Enjoy! (was: Re: Limit the length of transformed content from source text nodes)
From: Blue Gecko <bluegecko@xxxxxxxxx>
Date: Tue, 01 Nov 2005 10:40:40 +0100
gecko template
I've improved the hint suggested by David Carlisle (see below), allowing a snipping at arbitrary depth.

I'm pleased to share this humble piece of code, in case that someone else could need such a functionality, possibly improving it further on; I remind you that this stylesheet aims to emulate the shrinking mechanism commonly used in content summaries, where the bodies of available articles are snipped to their first words followed by ellipsis (...).

The current main limitation is that it performs just an identity transformation, so I had to arrange a double-pass transformation in order to manipulate my content semantics.

(Many thanks to David Carlisle)

==============

<!-- INPUT -->
<foo>
<content>
<section>
<title>1st section</title>
<content>
This is the <strong>1st part</strong> of an article interspersed with <strong>markup tags</strong> I'm striving to snip.
</content>
</section>
<section>
<title>2nd section</title>
<content>
<i>This is the <strong>2nd part</strong> of an article</i> interspersed with <strong>markup tags</strong> I'm striving to snip.
</content>
</section>
</content>
</foo>


==============

<!-- XSLT -->
<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0"
 >
 <xsl:variable name="snipSize" select="25"/>

 <xsl:template match="/">
  <root>
   <xsl:apply-templates mode="snippet" select="foo/content/node()[1]"/>
  </root>
 </xsl:template>

 <xsl:template match="*|text()" mode="snippet">
  <xsl:param name="currentLength" select="0"/>

<!-- Cumulative length of the current node. -->
<xsl:variable name="newLength" select="string-length(normalize-space(.)) + $currentLength"/>


  <xsl:choose>
   <!-- Text node -->
   <xsl:when test="self::text()">
    <xsl:choose>
     <!-- Does the text fit the lasting room? -->
     <xsl:when test="$newLength &lt;= $snipSize">
      <!-- Output the text content! -->
      <xsl:value-of select="normalize-space(.)"/>

<!-- Go to the next sibling (horizontal axis)! -->
<xsl:apply-templates select="following-sibling::node()[1]" mode="snippet">
<xsl:with-param name="currentLength" select="$newLength"/>
</xsl:apply-templates>
</xsl:when>
<!-- The lasting room is not enough. -->
<xsl:otherwise>
<!-- Snip the text (we can stop now, guys)! -->
<xsl:value-of select="substring(normalize-space(.), 1, $snipSize - $currentLength)"/>


      <xsl:text>[...]</xsl:text>
     </xsl:otherwise>
    </xsl:choose>
   </xsl:when>
   <!-- Any other kind of node -->
   <xsl:otherwise>
    <!-- Apply the identity transformation to the current node! -->
    <xsl:copy>
     <xsl:copy-of select="@*"/>

     <!-- Go deep inside the subnode hierarchy (vertical axis)! -->
     <xsl:apply-templates select="child::node()[1]" mode="snippet">
      <xsl:with-param name="currentLength" select="$currentLength"/>
     </xsl:apply-templates>
    </xsl:copy>

<!-- Is there any lasting room? -->
<xsl:if test="$newLength &lt;= $snipSize">
<!-- Go to the next sibling (horizontal axis)! -->
<xsl:apply-templates select="following-sibling::node()[1]" mode="snippet">
<xsl:with-param name="currentLength" select="$newLength"/>
</xsl:apply-templates>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>


==============

<!-- OUTPUT -->
<?xml version="1.0" encoding="UTF-8"?>
<root>
 <section>
  <title>1st section</title>
  <content>This is the<strong>1st[...]</strong></content>
 </section>
</root>

==============

David Carlisle wrote:
if you need to snip at arbitrary depth it gets harder, this just adds
complete elements until you are too long or snips top level text

==============

<foo>
<item>This is the <strong>body</strong> of an article interspersed with <strong>markup tags</strong> I'm striving to snip.</item>
</foo>


==============

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:variable name="tl" select="26"/>

<xsl:template match="foo">
<snippets>
<xsl:apply-templates/>
</snippets>
</xsl:template>
<xsl:template match="item">
<snippet>
<xsl:apply-templates mode="s" select="node()[1]"/>
</snippet>
</xsl:template>


<xsl:template match="strong">
<i>
<xsl:apply-templates/>
</i>
</xsl:template>
<xsl:template match="*" mode="s">
<xsl:param name="l" select="0"/>
<xsl:variable name="x">
<xsl:apply-templates select="."/>
</xsl:variable>
<xsl:variable name="xl" select="string-length($x)"/>
<xsl:choose>
<xsl:when test="$l + $xl &lt;= $tl">
<xsl:copy-of select="$x"/>
<xsl:apply-templates select="following-sibling::node()[1]" mode="s">
<xsl:with-param name="l" select="$l+$xl"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>[...]</xsl:otherwise>
</xsl:choose>
</xsl:template>


<xsl:template match="text()" mode="s">
<xsl:param name="l" select="0"/>

<xsl:variable name="xl" select="string-length(.)"/>
<xsl:choose>
<xsl:when test="$l + $xl &lt;= $tl">
 <xsl:value-of select="."/>
  <xsl:apply-templates select="following-sibling::node()[1]" mode="s">
    <xsl:with-param name="l" select="$l+$xl"/>
  </xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring(.,1,$l + $tl - $xl)"/>[...]</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

==============

$ saxon snip.xml snip.xsl
<?xml version="1.0" encoding="utf-8"?><snippets>
<snippet>This is the <i>body</i> of an a[...]</snippet>
</snippets>

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

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.
Email
First Name
Last Name
Company
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.