Re: [xsl] split string to whole words based on length

Subject: Re: [xsl] split string to whole words based on length
From: "andrew welch" <andrew.j.welch@xxxxxxxxx>
Date: Wed, 26 Apr 2006 18:00:51 +0100
On 4/26/06, David Carlisle <davidc@xxxxxxxxx> wrote:
>
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>                 version="2.0"
>
>  >
>
>
> <xsl:variable name="str" select="'one,two,three,four,five'" as="xs:string"
xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
> <xsl:variable name="length" select="10" as="xs:integer"
xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
>
> <xsl:output indent="yes"/>
>
> <xsl:template name="x">
> <xsl:analyze-string select="$str" regex=".{{0,{$length}}},">
>   <xsl:matching-substring>
>     <words><xsl:value-of
select="substring(.,1,string-length(.)-1)"/></words>
>   </xsl:matching-substring>
>   <xsl:non-matching-substring>
>     <words><xsl:value-of select="."/></words>
>   </xsl:non-matching-substring>
> </xsl:analyze-string>
> </xsl:template>
>
> </xsl:stylesheet>


This fails for the input:

<words>
<word>aaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</word>
<word>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</word>
</words>

It creates too many output elements.

Here's my attempt which is recursive and a bit large (which prompted
the question) but it does get the right answer:

<xsl:template name="splitString">
	<xsl:param name="str"/>
	<xsl:param name="length" select="$length"/>
	<xsl:param name="delim" select="','"/>
	<xsl:choose>
		<xsl:when test="string-length($str) &lt;= $length">
			<keywords><xsl:value-of select="$str"/></keywords>
		</xsl:when>
		<xsl:otherwise>

			<xsl:variable name="substring" select="substring($str, 1, $length)"/>

			<xsl:choose>
				<xsl:when test="starts-with(substring-after($str, $substring), $delim)">
					<!-- The split has occurred exactly on the delimeter -->
					<keyword><xsl:value-of select="$substring"/></keyword>
					<xsl:call-template name="splitString">
						<xsl:with-param name="str" select="substring-after($str,
concat($substring, ','))"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<!-- The split hass occurred mid word -->
					<xsl:variable name="subsubstring" select="for $x in
tokenize($substring, $delim) return concat($x, ',')[position() !=
last()]"/>

					<xsl:analyze-string select="$substring" regex="(.*),">
						<xsl:matching-substring>
							<keyword><xsl:value-of select="regex-group(1)"/></keyword>
							<xsl:call-template name="splitString">
								<xsl:with-param name="str" select="substring-after($str,
concat(regex-group(1), ','))"/>
							</xsl:call-template>
						</xsl:matching-substring>
					</xsl:analyze-string>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:otherwise>
	</xsl:choose>
</xsl:template>

Current Thread