Frédéric Schwebel schrieb:
Just curious if it has already been done : I need to center a string
with a max line length. The words must be uncut and balanced between
lines.
Here's a solution. Any comments concerning possible XSLT improvements
very welcome.
Michael Ludwig
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="text" select="'Just curious if it has already been
done : I need to center a string with a max line length. The words
must be uncut and balanced between lines.'" />
<xsl:variable name="text2" select="'Centering the lines is not a
problem. The most difficult part is to balance words with line-length.
Did somebody already do this with XSL ?'" />
<xsl:template name="wrap">
<xsl:param name="chars-max" tunnel="yes" as="xs:integer" select="30"/>
<xsl:param name="separator" tunnel="yes" as="xs:string" select="' '"/>
<xsl:param name="sep-len" tunnel="yes" as="xs:integer"
select="string-length($separator)" />
<!-- invariants tunneled above, others below -->
<xsl:param name="buffer" as="xs:string*" />
<xsl:param name="queue" as="xs:string*" />
<xsl:param name="chars-left" as="xs:integer" select="$chars-max" />
<!--
<xsl:message select="string-join(( string($chars-left), $buffer), '_')"/>
-->
<xsl:variable name="next" as="xs:string?" select="$queue[1]"/>
<xsl:variable name="add-len" as="xs:integer"
select="string-length( $next) + $sep-len"/>
<xsl:variable name="full" as="xs:boolean"
select="not($next) or $add-len > $chars-left" />
<xsl:if test="$full">
<xsl:for-each select="1 to ($chars-left + 1) idiv 2">
<xsl:text> </xsl:text>
</xsl:for-each>
<xsl:value-of select="string-join( $buffer, $separator)"/>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:if test="$next">
<xsl:call-template name="wrap">
<xsl:with-param name="buffer" select="
if ($full) then $next
else ($buffer, $next)"/>
<xsl:with-param name="queue" select="$queue[ position() > 1 ]"/>
<xsl:with-param name="chars-left" select="
if ($full) then $chars-max - $add-len
else $chars-left - $add-len"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="tokenizer" select="'\s+'" />
<xsl:for-each select="( $text, $text2 )">
<xsl:call-template name="wrap">
<xsl:with-param name="queue" select="tokenize( . , $tokenizer)" />
<!--
<xsl:with-param name="separator" select="'__'" tunnel="yes"/>
-->
</xsl:call-template>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--