|
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 |