xsl-list
[Top] [All Lists]

RE: [xsl] Center string

2009-06-11 19:59:01
-----Original Message-----
On Behalf Of Frédéric Schwebel

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


Hello,

Dealing with a minimum / maximum line length can be done with
regexp: they help produce, I think, more legible stylesheets
-- although it may be a question of taste. See for example this
stylesheet:


<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:p="some namespace">

<xsl:output method="text" indent="no" encoding="ISO-8859-1"/>
<xsl:param name="line-length" select="30"/>

<xsl:template match="/root">
  <xsl:for-each select="text">
    <xsl:call-template name="cut"/>
    </xsl:for-each>
  </xsl:template>

<xsl:template name="cut">
  <xsl:variable name="length" select="if
    (not(contains(substring(.,1,$line-length),' ')))
      then string-length(substring-before(.,' '))
      else $line-length"/>
  <xsl:analyze-string select="." regex="^.{{0,{$length}}}(\s|.$)">
    <xsl:matching-substring>
      <xsl:value-of select="p:center(.)"/>
      </xsl:matching-substring>
    <xsl:non-matching-substring>
      <xsl:choose>
        <xsl:when test="contains(.,' ')">
          <xsl:call-template name="cut"/>
          </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="p:center(.)"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:template>

<xsl:function name="p:center">
  <xsl:param name="line"/>
  <xsl:for-each select="1 to ($line-length - string-length($line)) idiv 2">
    <xsl:value-of select="' '"/>
    </xsl:for-each>
  <xsl:value-of select="concat($line,'&#13;&#10;')"/>
  </xsl:function>

</xsl:stylesheet>


The 'cut' template uses the regexp   ^.{0,30}(\s|.$)
which matches up to 30 characters from the start of the
string, up to either a space or the end of the string.

(The "length" parameter deals with words that are longer
than the line-length, which would otherwise trigger an
infinite loop, by adjusting the line-length (30) to the
length of the word).


Given this source file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
 <text>abcde abcde abcde abcde abcde abcde abcde abcde abcde abcde abcde abcde 
abcde abcde abcde abcde abcde</text>
 <text>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</text>
 <text>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.</text>
 <text>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 ?</text>
 <text>Also deals with words longer than the accepted line-length such as 
anticonstitutionnellementmentment and some more text after that tagada.</text>
 <text>¨mathématiques niveau lycée: série '1</text>
 </root>


it gives this result:

abcde abcde abcde abcde abcde 
abcde abcde abcde abcde abcde 
abcde abcde abcde abcde abcde 
         abcde abcde
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
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.
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 ?
Also deals with words longer 
than the accepted line-length 
           such as 
anticonstitutionnellementmentment 
and some more text after that 
           tagada.
¨mathématiques niveau lycée: 
           série '1


(Note that it does not normalize the input
strings -- which may or may not be desired).

In your first message you seemed to imply that
you wanted "série" and "'1" kept together in all
cases: this calls for the replacement of any
space between those words with an unbreakable
space (which is of course easier if there is
a recognizable pattern, but it seems to be the
case?)

HTH

Regards,
EB




--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>