RE: [xsl] Re: Re: Fixed Line Length Output

Subject: RE: [xsl] Re: Re: Fixed Line Length Output
From: "Cynthia DeLaria" <cdelaria@xxxxxxxxx>
Date: Tue, 9 Dec 2003 10:07:40 -0700
Thanks. Though this is already where I was, except that you simply cut
off the lines and got rid of the rest of the content. And whatever file
you're importing here is not included anywhere.

When I figure out what I'm trying to do, I'll email the list.

Thanks anyway.

Cynthia

-----Original Message-----
From: Dimitre Novatchev [mailto:dnovatchev@xxxxxxxxx] 
Sent: Monday, December 08, 2003 11:05 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] Re: Re: Fixed Line Length Output


"Cynthia DeLaria" <cdelaria@xxxxxxxxx> wrote in message
news:CE54CE22EF3A65438885197A240E408BC5C173@xxxxxxxxxxxxxxxxxxx
> Hello, all.
>
> Thank you for tackling this subject. I have been wrestling with this 
> same thing as I have a templating system that generates text e-mail 
> messages where the line length can be no more than 72 characters. This

> example has opened up some interesting options as far as how to do 
> that with certain pieces...
>
> However, this example assumes that the information gotten from a node 
> is never going to be longer than 25 characters (or whatever the 
> desired length is). In my case I have movie descriptions that are 
> often times 300-400 characters in length, and I need to put 
> line-breaks every 72 characters (or where it makes sense to do so). Is

> there any way to account for this? Here is example xml:

This was done two years ago -- see e.g:
    http://sources.redhat.com/ml/xsl-list/2001-12/msg00651.html

FXSL contains the "str-split-to-lines" template that solves this class
of problems.

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:ext="http://exslt.org/common";
xmlns:str-split2lines-func="f:str-split2lines-func"
exclude-result-prefixes="xsl ext str-split2lines-func"
>


   <xsl:import href="dvc-str-foldl.xsl"/>

   <!-- to be applied on text.xml -->

   <str-split2lines-func:str-split2lines-func/>

   <xsl:output indent="yes" omit-xml-declaration="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="@*|node()">
     <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
     </xsl:copy>
   </xsl:template>

    <xsl:template match="text()">
      <xsl:value-of select="'&#xA;'"/>
      <xsl:call-template name="str-split-to-lines">
        <xsl:with-param name="pStr" select="."/>
        <xsl:with-param name="pLineLength" select="64"/>
        <xsl:with-param name="pDelimiters" select="' &#9;&#10;&#13;'"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template name="str-split-to-lines">
      <xsl:param name="pStr"/>
      <xsl:param name="pLineLength" select="60"/>
      <xsl:param name="pDelimiters" select="' &#9;&#10;&#13;'"/>

      <xsl:variable name="vsplit2linesFun"
                    select="document('')/*/str-split2lines-func:*[1]"/>

      <xsl:variable name="vrtfParams">
       <delimiters><xsl:value-of select="$pDelimiters"/></delimiters>
       <lineLength><xsl:copy-of select="$pLineLength"/></lineLength>
      </xsl:variable>

      <xsl:variable name="vResult">
       <xsl:call-template name="dvc-str-foldl">
         <xsl:with-param name="pFunc" select="$vsplit2linesFun"/>
         <xsl:with-param name="pStr" select="$pStr"/>
         <xsl:with-param name="pA0" select="ext:node-set($vrtfParams)"/>
       </xsl:call-template>
      </xsl:variable>

      <xsl:for-each select="ext:node-set($vResult)/line">
        <xsl:for-each select="word">
          <xsl:value-of select="concat(., ' ')"/>
        </xsl:for-each>
        <xsl:value-of select="'&#xA;'"/>
      </xsl:for-each>
    </xsl:template>

    <xsl:template match="str-split2lines-func:*">
      <xsl:param name="arg1" select="/.."/>
      <xsl:param name="arg2"/>

      <xsl:copy-of select="$arg1/*[position() &lt; 3]"/>
      <xsl:copy-of select="$arg1/line[position() != last()]"/>

   <xsl:choose>
     <xsl:when test="contains($arg1/*[1], $arg2)">
       <xsl:if test="string($arg1/word)">
          <xsl:call-template name="fillLine">
            <xsl:with-param name="pLine" select="$arg1/line[last()]"/>
            <xsl:with-param name="pWord" select="$arg1/word"/>
            <xsl:with-param name="pLineLength" select="$arg1/*[2]"/>
          </xsl:call-template>
       </xsl:if>
     </xsl:when>
     <xsl:otherwise>
       <xsl:copy-of select="$arg1/line[last()]"/>
       <word><xsl:value-of select="concat($arg1/word, $arg2)"/></word>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

      <!-- Test if the new word fits into the last line -->
<xsl:template name="fillLine">
      <xsl:param name="pLine" select="/.."/>
      <xsl:param name="pWord" select="/.."/>
      <xsl:param name="pLineLength" />

      <xsl:variable name="vnWordsInLine" select="count($pLine/word)"/>
      <xsl:variable name="vLineLength"
       select="string-length($pLine) + $vnWordsInLine"/>
      <xsl:choose>
        <xsl:when test="not($vLineLength + string-length($pWord)
                           >
                            $pLineLength)">
          <line>
            <xsl:copy-of select="$pLine/*"/>
            <xsl:copy-of select="$pWord"/>
          </line>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select="$pLine"/>
          <line>
            <xsl:copy-of select="$pWord"/>
          </line>
          <word/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

when applied on your source.xml:

<t>
  <movieDesc>
    <description>They were betrayed by one of their own. Now the next
heist isn't just about money - it's about payback.</description>
    <description>One's an amateur real estate broker. The other's a yoga
instructor. Believe it or not, they're also two of LA's finest
detectives!</description>
    <description>The mild-mannered Jerry has second thoughts about his
daughter's wedding when he meets the groom's outrageous
father!</description>
    <description>Return to the swinging sixties with Renee Zellweger and
Ewan McGregor as they engage in a stylish battle of the
sexes.</description>
    <description>When Willard decides it's time for revenge, his loyal,
furry friends become his own personal army.</description>
    <description>Young friends lost deep in the Appalachian hills race
to find civilization as they're pursued by horrors beyond their
imagination.</description>
    <description>Two girls must wade through the emotional debris that
clutters their lives after a tragic event brings them
together.</description>
  </movieDesc>
</t>

produces the wanted output (every line's length is as close as possible
to but not exceeding 64 and no word has been split into two:

<t>
   <movieDesc>
      <description>
They were betrayed by one of their own. Now the next heist isn't just
about money - it's about </description>
      <description>
One's an amateur real estate broker. The other's a yoga instructor.
Believe it or not, they're also two of LA's finest </description>
      <description>
The mild-mannered Jerry has second thoughts about his daughter's wedding
when he meets the groom's outrageous </description>
      <description>
Return to the swinging sixties with Renee Zellweger and Ewan McGregor as
they engage in a stylish battle of the </description>
      <description>
When Willard decides it's time for revenge, his loyal, furry friends
become his own personal </description>
      <description>
Young friends lost deep in the Appalachian hills race to find
civilization as they're pursued by horrors beyond their </description>
      <description>
Two girls must wade through the emotional debris that clutters their
lives after a tragic event brings them </description>
   </movieDesc>
</t>


Hope this helped.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL




 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread