[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Center string

Subject: Re: Center string
From: Frédéric Schwebel <Fred.Schwebel@xxxxxxxxxxx>
Date: Thu, 11 Jun 2009 15:19:03 +0200
Re:  Center string
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 &#10; 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)) &lt; $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)) &lt;=
$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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.