Michael Ludwig schrieb:
Here's a solution. Any comments concerning possible XSLT improvements
very welcome.
I think I found an improvement. Instead of reslicing sequences (possibly
involving a copy operation internally, depending on the implementation),
I increment an integer to move ahead in a tunneled sequence (that I
think won't be copied). Comments concerning XSLT technique 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="t0" select="'abcde abcde abcde abcde abcde abcde
abcde abcde abcde abcde abcde abcde abcde abcde abcde abcde abcde'"/>
<xsl:variable name="t1" select="'abcd abcd abcd abcd abcd abcd abcd abcd
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd'"/>
<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="queue" tunnel="yes" as="xs:string*" />
<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="offset" as="xs:integer" select="1" />
<xsl:param name="length" as="xs:integer" select="1" />
<xsl:param name="chars-left" as="xs:integer"
select="$chars-max - string-length( $queue[1])" />
<xsl:variable name="next" as="xs:string?"
select="$queue[$offset + $length]"/>
<xsl:variable name="next-len" as="xs:integer"
select="string-length( $next)"/>
<xsl:variable name="full" as="xs:boolean"
select="not($next) or $sep-len + $next-len > $chars-left" />
<xsl:if test="$full">
<xsl:for-each select="1 to (($chars-left + 1) idiv 2) - 1">
<xsl:text> </xsl:text>
</xsl:for-each>
<xsl:value-of select="string-join(
subsequence( $queue, $offset, $length), $separator)"/>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:if test="$next">
<xsl:call-template name="wrap">
<xsl:with-param name="offset" select="
if ($full) then $offset + $length
else $offset"/>
<xsl:with-param name="length" select="
if ($full) then 1 else $length + 1"/>
<xsl:with-param name="chars-left" select="
if ($full) then $chars-max - $next-len
else $chars-left - $sep-len - $next-len"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="tokenizer" select="'\s+'" />
<xsl:for-each select="( $t0, $t1, $text, $text2 )">
<xsl:call-template name="wrap">
<xsl:with-param name="queue" tunnel="yes"
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>
--~--