Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
XML
data.xmlanalysis
mappoint.webservice
msf
msxml-webrelease
netmyservices.sdk
passport.sdk
soap
soapsdk
uddi.general
uddi.programming
uddi.specification
xml
xmlsqlwebrelease
xsl
  
 
date: Wed, 06 Feb 2008 19:47:46 +0100,    group: microsoft.public.xsl        back       


Implementing a "State Machine" in XSL?   
Hello,

i need to use XSL to truncate a HTML fragment, keeping the tags intact.
So for example, i want to truncate this HTML to include ~15 visible 
characters:

<b>This is a <span style="color: #888">very long</span> Text</b>

The result should be:
<b>This is a <span style="color: #888">very </span></b>

As you see, i ignore the tags and count to 15. But then i may have open 
tags, so i close the open tags (which means i somehow need to keep track 
of which tags are still open).

In conventional programming, i would use a state machine for this, but I 
do not know enough about XSLT to do that.

Any hints?

-- 
http://www.Stum.de · http://www.Souvenance.net

e-Mail Adresse ist gültig, wird aber äußerst selten gelesen.
e-Mail address is valid, but read very infrequently.
date: Wed, 06 Feb 2008 19:47:46 +0100   author:   Michael Stum

Re: Implementing a "State Machine" in XSL?   
That's trivial in XSLT 2.0 and a bit cumbersome in pure XSLT 1.0.

One idea is to traverse the tree in document order and checking if 
current element would exceed max length. If it would not then output it 
and move to the next one. If it would, process this node children 
recursively. If you come down to a text node that's too long, split it.

Here is a sketch implementation. It's far from perfect, but you get the 
idea.

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

   <xsl:param name="max-len" select="15"/>

   <xsl:template match="/">
     <xsl:call-template name="output">
       <xsl:with-param name="nodes" select="*"/>
     </xsl:call-template>
   </xsl:template>

   <xsl:template name="output">
     <xsl:param name="running-length" select="0"/>
     <xsl:param name="nodes" select="/.."/>

     <xsl:choose>
       <xsl:when test="string-length($nodes[1]) + $running-length <= 
$max-len">
         <xsl:copy-of select="$nodes[1]"/>
         <xsl:if test="$nodes[2]">
           <xsl:call-template name="output">
             <xsl:with-param name="running-length" 
select="string-length($nodes[1]) + $running-length"/>
             <xsl:with-param name="nodes" select="$nodes[position() != 
1]|$nodes[1]/*"/>
           </xsl:call-template>
         </xsl:if>
       </xsl:when>
       <xsl:when test="$nodes[1]/self::text()">
         <xsl:value-of select="substring($nodes[1], 1, $max-len - 
$running-length)"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:if test="$nodes[1]/node()">
           <xsl:element name="{name($nodes[1])}" 
namespace="{namespace-uri($nodes[1])}">
             <xsl:copy-of select="$nodes[1]/@*"/>
             <xsl:call-template name="output">
               <xsl:with-param name="running-length" 
select="$running-length"/>
               <xsl:with-param name="nodes" select="$nodes[1]/node()"/>
             </xsl:call-template>
           </xsl:element>
         </xsl:if>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:template>
</xsl:stylesheet>


-- 
Oleg

Michael Stum wrote:
> Hello,
> 
> i need to use XSL to truncate a HTML fragment, keeping the tags intact.
> So for example, i want to truncate this HTML to include ~15 visible 
> characters:
> 
> <b>This is a <span style="color: #888">very long</span> Text</b>
> 
> The result should be:
> <b>This is a <span style="color: #888">very </span></b>
> 
> As you see, i ignore the tags and count to 15. But then i may have open 
> tags, so i close the open tags (which means i somehow need to keep track 
> of which tags are still open).
> 
> In conventional programming, i would use a state machine for this, but I 
> do not know enough about XSLT to do that.
> 
> Any hints?
>
date: Thu, 07 Feb 2008 13:11:56 +0200   author:   Oleg Tkachenko

Re: Implementing a "State Machine" in XSL?   
Oleg Tkachenko schrieb:
> That's trivial in XSLT 2.0 and a bit cumbersome in pure XSLT 1.0.

As always in life, i of course only have XSLT 1.0 (Sharepoint 2007) :-)

> One idea is to traverse the tree in document order and checking if 
> current element would exceed max length. If it would not then output it 
> and move to the next one. If it would, process this node children 
> recursively. If you come down to a text node that's too long, split it.
> 
> Here is a sketch implementation. It's far from perfect, but you get the 
> idea.

Thank you! I'll look at that.

> 
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> 
>   <xsl:param name="max-len" select="15"/>
> 
>   <xsl:template match="/">
>     <xsl:call-template name="output">
>       <xsl:with-param name="nodes" select="*"/>
>     </xsl:call-template>
>   </xsl:template>
> 
>   <xsl:template name="output">
>     <xsl:param name="running-length" select="0"/>
>     <xsl:param name="nodes" select="/.."/>
> 
>     <xsl:choose>
>       <xsl:when test="string-length($nodes[1]) + $running-length <= 
> $max-len">
>         <xsl:copy-of select="$nodes[1]"/>
>         <xsl:if test="$nodes[2]">
>           <xsl:call-template name="output">
>             <xsl:with-param name="running-length" 
> select="string-length($nodes[1]) + $running-length"/>
>             <xsl:with-param name="nodes" select="$nodes[position() != 
> 1]|$nodes[1]/*"/>
>           </xsl:call-template>
>         </xsl:if>
>       </xsl:when>
>       <xsl:when test="$nodes[1]/self::text()">
>         <xsl:value-of select="substring($nodes[1], 1, $max-len - 
> $running-length)"/>
>       </xsl:when>
>       <xsl:otherwise>
>         <xsl:if test="$nodes[1]/node()">
>           <xsl:element name="{name($nodes[1])}" 
> namespace="{namespace-uri($nodes[1])}">
>             <xsl:copy-of select="$nodes[1]/@*"/>
>             <xsl:call-template name="output">
>               <xsl:with-param name="running-length" 
> select="$running-length"/>
>               <xsl:with-param name="nodes" select="$nodes[1]/node()"/>
>             </xsl:call-template>
>           </xsl:element>
>         </xsl:if>
>       </xsl:otherwise>
>     </xsl:choose>
>   </xsl:template>
> </xsl:stylesheet>
> 
> 


-- 
http://www.Stum.de · http://www.Souvenance.net

e-Mail Adresse ist gültig, wird aber äußerst selten gelesen.
e-Mail address is valid, but read very infrequently.
date: Mon, 11 Feb 2008 21:27:58 +0100   author:   Michael Stum

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us