xsl-list
[Top] [All Lists]

Re: Reverse Tokens Template

2003-05-15 10:47:09
Stephen Greene wrote:

Hi,

I have been trying to modify (un-sucessfully) Dimitre Novatchev's template
to reverse the order of "words" in a string (words being character
substrings seperated by a space character). Such that the string "hello
world" would become "world hello".
I was wondering if anyone would be able to offer any hints on how to
accomplish this.

I have tried modifying the template but as the word length is variable,
(and
the words need to go back into a string, and not be output) I have been
unsuccessful in concatenating the string after removing one word at a
time.

If this is not possible, is there a way in which I could remove one word
at
a time from the end of the string?
(in a substring-before($theString, ' ') like way) Instead of the
beginning?

I thank you for your time and for your help,

Regards,

Stephen Greene

National Research Council of Canada

Hi Stephen,

This is not pretty but it works. As David suggested I first reversed the
whole string then worked through the reversed string, breaking out and
reversing individual words.

I've just trashed this up so no doubt it could stand some tidy up and there
may well be a cleaner way to do it.

HTH

cheers

Malcolm


Test XML:

<sentences>

<sentence>a quick brown fox jumped over</sentence>

<sentence>mary had a little lamb</sentence>

<sentence></sentence>

</sentences>



XSLT:

<?xml version="1.0" encoding="UTF-8"?>

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">

<xsl:apply-templates/>

</xsl:template>

<xsl:template match="sentences">

<xsl:copy>

<xsl:apply-templates/>

</xsl:copy>

</xsl:template>

<xsl:template match="sentence">

<!-- 

first reverse the whole string-->

<xsl:variable name="reversedString">

<xsl:call-template name="reverseString">

<xsl:with-param name="str" select="normalize-space(.)"/>

</xsl:call-template>

</xsl:variable>

<!--

now break out each word in the reversed string and reverse it back-->

<xsl:variable name="reversedStringNonReversedWords">

<xsl:call-template name="reverseWords">

<xsl:with-param name="str" select="$reversedString"/>

</xsl:call-template>

</xsl:variable>

<!--

Put the original + the two steps of reversed strings into the output-->

<xsl:copy-of select="."/>

<sentence>

<xsl:value-of select="$reversedString"/>

</sentence>

<sentence>

<xsl:value-of select="$reversedStringNonReversedWords"/>

</sentence>

</xsl:template>

<!--


template outputs the reverse of $str.

-->

<xsl:template name="reverseString">

<xsl:param name="str"/>

<xsl:call-template name="recursiveCharSwapper">

<xsl:with-param name="str" select="$str"/>

<xsl:with-param name="charPos" select="string-length( $str )"/>

</xsl:call-template>

</xsl:template>

<!--



-->

<xsl:template name="reverseWords">

<xsl:param name="str"/>

<!--

testWord will either be the first word in $str or a nullstring if $str does
not contain a space-->

<xsl:variable name="testWord" select="substring-before( $str , ' ' )"/>

<!--

get $word by checking $testWord-->

<xsl:variable name="word">

<xsl:choose>

<xsl:when test=" $testWord = '' ">

<xsl:value-of select="$str"/>

</xsl:when>

<xsl:otherwise>

<xsl:value-of select="$testWord"/>

</xsl:otherwise>

</xsl:choose>

</xsl:variable>

<!--


simply pass $word into the recursive function which will output the reverse
of $word-->


<xsl:call-template name="recursiveCharSwapper">

<xsl:with-param name="str" select="$word"/>

<xsl:with-param name="charPos" select="string-length($word)"/>

</xsl:call-template>

<!--


if we are not yet at the end of $str then we recall this template with just
the string after the first word

-->

<xsl:if test="string-length($word) &lt; string-length($str)">

<!-- we manually add the space between the words-->

<xsl:text> </xsl:text>

<xsl:call-template name="reverseWords">

<xsl:with-param name="str" select="substring-after( $str , ' ' )"/>

</xsl:call-template>

</xsl:if>

</xsl:template>

<!--




Recursive template outputs the Char in $charPos in $str, and recurses to
$charPos - 1

-->

<xsl:template name="recursiveCharSwapper">

<xsl:param name="str"/>

<xsl:param name="charPos"/>

<xsl:value-of select="substring( $str , $charPos , 1 )"/>

<xsl:if test="$charPos &gt; 1">

<xsl:call-template name="recursiveCharSwapper">

<xsl:with-param name="str" select="$str"/>

<xsl:with-param name="charPos" select="$charPos - 1"/>

</xsl:call-template>

</xsl:if>

</xsl:template>

</xsl:stylesheet>



Output:

<sentences>

<sentence>a quick brown fox jumped over</sentence>

<sentence>revo depmuj xof nworb kciuq a</sentence>

<sentence>over jumped fox brown quick a</sentence>

<sentence>mary had a little lamb</sentence>

<sentence>bmal elttil a dah yram</sentence>

<sentence>lamb little a had mary</sentence>

<sentence />

<sentence />

<sentence />

</sentences>









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



<Prev in Thread] Current Thread [Next in Thread>