Subject: Re: [xsl] Center string From: Frédéric Schwebel <Fred.Schwebel@xxxxxxxxxxx> Date: Thu, 11 Jun 2009 15:19:03 +0200 |
Hi, I already did everything you say :) Problem is with step 2c "flow the words into lines breaking each line AT THE CLOSEST possible point to the average line length." The closest is quite hard to know. I just said "if the current line length + 1 (space) + current word length <= average line length, put the word in the same line, otherwise put it on a new line". But I'll change it and do some tries. I'm about to find a correct solution. If you're interested, here's my code (sorry it's french. $sautAGenerer will be translated to in output, $carcoup are marking chars that won't be output so removed when calculating lengthes) : [...] <xsl:variable name="longueur2" as="xs:integer" select="$longueur - 6" /> <xsl:variable name="nbLignesIdeal" as="xs:integer" select="xs:integer(ceiling(string-length(translate(.,$carcoup,'')) div $longueur2))" /> <xsl:variable name="longueurIdeale" as="xs:integer" select="xs:integer(round(string-length(translate(.,$carcoup,'')) div $nbLignesIdeal))"/> <xsl:variable name="titreMisEnPage" as="xs:string" select="string-join(doc:centreTitre(tokenize(.,'&pt;'), $longueurIdeale,$longueur2,''),'')" /> [...] <xsl:variable name="lignesTitre" as="xs:string*" select="tokenize(translate($titreMisEnPage,' ',''),$sautAGenerer)" /> <xsl:for-each select="$lignesTitre"> <xsl:value-of select="functx:repeat-string('&pt;',3 + xs:integer(floor(($longueur2 - string-length(.)) div 2)))" /> <xsl:value-of select="concat(.,$sautAGenerer)" /> </xsl:for-each> [...] <!-- fonction de mise en ligne des titres avant centrage --> <xsl:function name="doc:centreTitre" as="xs:string*"> <xsl:param name="mots" as="xs:string*" /> <xsl:param name="longueurIdeale" as="xs:integer" /> <xsl:param name="longueurMax" as="xs:integer" /> <xsl:param name="dejaFait" as="xs:string?" /> <xsl:variable name="derniereLigne" as="xs:string" select='functx:substring-after-last($dejaFait,$sautAGenerer)' /> <xsl:variable name="motCourant" as="xs:string" select="translate($mots[1],$carcoup,'')" /> <xsl:variable name="longueurIdealeCourante" as="xs:integer"> <xsl:choose> <xsl:when test="($longueurIdeale + round(string-length($motCourant) div 2)) < $longueurMax"> <xsl:value-of select="xs:integer($longueurIdeale + round(string-length($motCourant) div 2))" /> </xsl:when> <xsl:otherwise><xsl:value-of select="$longueurIdeale" /> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="motMisEnPage" as="xs:string"> <xsl:choose> <!-- cas 1 : on est en dibut de ligne --> <xsl:when test="string-length($derniereLigne)=0"> <xsl:value-of select="$motCourant" /> </xsl:when> <!-- cas 2 : le mot rentre dans la ligne de (longueur ideale + moitie longueur mot courant)--> <xsl:when test="string-length(concat($derniereLigne,$espace,$motCourant)) <= $longueurIdeale"> <xsl:value-of select="concat($espace,$motCourant)" /> </xsl:when> <!-- cas 3 : faut passer ` la ligne --> <xsl:otherwise> <xsl:value-of select="concat($sautAGenerer,$motCourant)" /> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:value-of select="functx:trim($motMisEnPage)" /> <xsl:if test="count($mots) > 1"> <xsl:value-of select="doc:centreTitre($mots[position() > 1], $longueurIdeale, $longueurMax, concat(functx:trim($dejaFait),functx:trim($motMisEnPage)))" /> </xsl:if> </xsl:function> 2009/6/11 Michael Kay <mike@xxxxxxxxxxxx>: > > I think you need to move from > > (0) a set of examples, to > > (1) a requirement statement, to > > (2) an algorithm, to > > (3) an implementation in XSLT code. > > Perhaps (1) is something like: generate the output in as few lines as > possible given the maximum line length, and then divide the words between > lines so as to minimize the maximum variation between actual line length and > average line length. > > Perhaps (2) is something like: > > (a) compute the minimum number of lines by first trying to pack the words > as densely as possible. > > (b) compute the average line length by dividing the total length by the > minimum number of lines > > (c) flow the words into lines breaking each line at the closest possible > point to the average line length. > > If that's OK, then step (3) is relatively straightforward so long as you are > comfortable with recursion, though like most such things it's likely to be > much easier in XSLT 2.0 than in 1.0. > > Regards, > > Michael Kay > http://www.saxonica.com/ > http://twitter.com/michaelhkay
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Center string, Michael Kay | Thread | RE: [xsl] Center string, Emmanuel Bégué |
RE: [xsl] Center string, Michael Kay | Date | Re: [xsl] Center string, Michael Ludwig |
Month |