Subject: Re: [xsl] RE: XSL-FO and Z-index From: Jesper Tverskov <jesper.tverskov@xxxxxxxxx> Date: Thu, 20 Sep 2012 23:09:40 +0200 |
Let me answer my question myself then, can probably be improved, and I might have forgotten something. The functions return number of lines a text will be divided into (no hyphenation) at a given line length. Should work for mono spaced characters. For proportional text, $maxLineLength must be set to a figure lower than real line length. I guess one could take a look at a couple of pages of standard text and calculate average max line length and use that for $maxLineLength. Number of lines is not just character count including spaces divided with line length. When there is not room for a word it moves to next line. It could result in many additional lines depending on the length of the text. <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:output indent="yes"/> <xsl:template name="start"> <xsl:variable name="text">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</xsl:variable> <xsl:variable name="number-of-lines"> <xsl:call-template name="create-sequence-of-character-counts"> <xsl:with-param name="text" select="$text"/> <xsl:with-param name="maxLineLength" select="80"/> </xsl:call-template> </xsl:variable> <!-- Output --> <xsl:value-of select="$number-of-lines"/> </xsl:template> <xsl:template name="create-sequence-of-character-counts"> <xsl:param name="text"/> <xsl:param name="maxLineLength"/> <xsl:variable name="seq-of-words" select="tokenize(normalize-space($text), ' ')"/> <!-- string-length of spaces + 1 = number of items --> <xsl:variable name="number-of-items" select="string-length(replace(normalize-space($text), '\S', '')) + 1"/> <!-- there must be a smarter way to do the following --> <!-- we add the missing space (after the word) to string-length to get character count for item --> <xsl:variable name="seqCount"> <X> <xsl:for-each select="$seq-of-words[position()]"> <x> <xsl:value-of select="concat((string-length(.) + 1), ' ')"/> </x> </xsl:for-each> </X> </xsl:variable> <xsl:variable name="string-of-character-counts"> <xsl:value-of select="normalize-space($seqCount)" separator=" "/> </xsl:variable> <xsl:variable name="seq-of-character-counts" select="tokenize($string-of-character-counts, ' ')" as="item()+"/> <xsl:for-each select="$seq-of-character-counts[position()]"> <xsl:if test="$maxLineLength le xs:integer(.)"> <xsl:message terminate="yes" select="'At least one word is longer than maxLineLength'"/> </xsl:if> </xsl:for-each> <xsl:call-template name="seqCounts2lines"> <xsl:with-param name="seqCounts" select="$seq-of-character-counts" as="item()+"/> <xsl:with-param name="number-of-items" select="$number-of-items"/> <xsl:with-param name="maxLineLength" select="$maxLineLength"/> </xsl:call-template> </xsl:template> <xsl:template name="seqCounts2lines"> <xsl:param name="seqCounts"/> <xsl:param name="number-of-items" as="xs:integer"/> <xsl:param name="itemSum" select="0" as="xs:integer"/> <xsl:param name="nextItem" select="1" as="xs:integer"/> <xsl:param name="lines" select="1" as="xs:integer"/> <xsl:param name="maxLineLength"/> <xsl:choose> <xsl:when test="$nextItem le ($number-of-items)"> <xsl:choose> <xsl:when test="$itemSum + xs:integer(subsequence($seqCounts, $nextItem, 1)) lt $maxLineLength"> <xsl:call-template name="seqCounts2lines"> <xsl:with-param name="itemSum" select="$itemSum + xs:integer(subsequence($seqCounts, $nextItem, 1))"/> <xsl:with-param name="nextItem" select="$nextItem + 1" as="xs:integer"/> <xsl:with-param name="seqCounts" select="$seqCounts" as="item()+"/> <xsl:with-param name="number-of-items" select="$number-of-items"/> <xsl:with-param name="lines" select="$lines" as="xs:integer"/> <xsl:with-param name="maxLineLength" select="$maxLineLength"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="seqCounts2lines"> <xsl:with-param name="itemSum" select="0"/> <xsl:with-param name="nextItem" select="$nextItem" as="xs:integer"/> <xsl:with-param name="seqCounts" select="$seqCounts" as="item()+"/> <xsl:with-param name="number-of-items" select="$number-of-items"/> <xsl:with-param name="lines" select="$lines + 1" as="xs:integer"/> <xsl:with-param name="maxLineLength" select="$maxLineLength"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select="$lines"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Cheers Jesper Tverskov http://www.xmlplease.com
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] RE: XSL-FO and Z-index, Jesper Tverskov | Thread | Re: [xsl] RE: XSL-FO and Z-index, Liam R E Quin |
Re: [xsl] position last and attribu, David Carlisle | Date | Re: [xsl] position last and attribu, Michael Kay |
Month |