Subject: Re: [xsl] Center string From: Michael Ludwig <mlu@xxxxxxxxxxxxx> Date: Thu, 11 Jun 2009 20:24:17 +0200 |
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.
<?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: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>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Center string, Michael Ludwig | Thread | [xsl] total newbie, Bill Smith |
Re: [xsl] Discrepancy in handling c, Alain | Date | [xsl] total newbie, Bill Smith |
Month |