This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: String parsing, node creation


Michael Clark wrote:
> Hello, and thanks in advance for reading my question!
> 
> I'll jump right into the code, since it explains itself better than I can.
> 
> <!-- My source XML -->
> <doc>
> 	<txt>
> 		This will be a fairly large block of text.
> 		Text block text block text block text block.
> 		It will go on for a while ... then stop.
> 	</txt>
> </doc>
> 
> The problem I have now, is as follows: My <txt> nodes may only have #text
> nodes of a certain, very short length (say, 38 characters).
> 
> So, after proper translation my xml document should look as follows:
> 
> <doc>
> 	<txt>This will be a 256 char block of text.</txt>
> 	<txt> Text block text block text block text</txt>
> 	<txt> block.  It will go on for a while ...</txt>
> 	<txt>then stop.</txt>
> </doc>
> 
> The real hitch is the #text must be broken up by word blocks (words
> tokenized by space (' '), not purely by character length.

I'll assume you are just asking for word wrap, and don't really
need, as your example suggests, left-padding of certain lines
(but not all of them) with spaces to reach 38 character widths.

The following is not the exact solution you need, but it only requires
a small amount of tweaking to emit the enclosing elements for each line.
I'd be interested to know if there's an easier way.

To use it, just call the wrap-multiline template, passing it the 'text'
variable containing the text to wrap, and setting the 'maxwidth' variable to
the column width desired (I use a top-level param for this, so I can set it
externally):

  <!-- max width to wrap to -->
  <xsl:param name="maxwidth" select="78"/>

  <!-- split lines at n characters without truncating words -->
  <!-- and preserve existing linefeeds -->
  <xsl:template name="wrap-multiline">
    <xsl:param name="text"/>
    <xsl:choose>
      <xsl:when test="contains($text,'&#10;')">
        <xsl:call-template name="justify">
          <xsl:with-param name="width" select="$maxwidth"/>
          <xsl:with-param name="txt" select="substring-before($text,'&#10;')"/>
        </xsl:call-template>
        <xsl:text>&#10;</xsl:text>
        <xsl:call-template name="wrap-multiline">
          <xsl:with-param name="text" select="substring-after($text,'&#10;')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$text">
        <xsl:call-template name="justify">
          <xsl:with-param name="width" select="$maxwidth"/>
          <xsl:with-param name="txt" select="$text"/>
        </xsl:call-template>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="justify">
    <xsl:param name="txt" /> 
    <xsl:param name="width" /> 
    <xsl:choose>
      <xsl:when test="$width &lt; string-length($txt)">
        <xsl:variable name="real-width">
          <xsl:call-template name="tune-width">
            <xsl:with-param select="$txt" name="txt" /> 
            <xsl:with-param select="$width" name="width" /> 
            <xsl:with-param select="$width" name="def" /> 
          </xsl:call-template>
        </xsl:variable>
        <!--
           this is where you'd do something like
           <txt>
             <xsl:value-of select="substring($txt, 1, $real-width)"/>
           </txt>
           instead of the value-of below...
        -->
        <xsl:value-of select="concat(substring($txt, 1, $real-width),'&#10;')" /> 
        <xsl:call-template name="justify">
          <xsl:with-param select="substring($txt,$real-width + 1)" name="txt" /> 
          <xsl:with-param select="$width" name="width" /> 
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$txt"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="tune-width">
    <xsl:param name="txt" /> 
    <xsl:param name="width" /> 
    <xsl:param name="def" /> 
    <xsl:choose>
      <xsl:when test="$width = 0">
        <xsl:value-of select="$def" /> 
      </xsl:when>
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="substring($txt, $width, 1 ) = ' '">
            <xsl:value-of select="$width" /> 
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="tune-width">
              <xsl:with-param select="$txt" name="txt" /> 
              <xsl:with-param select="$width - 1" name="width" /> 
              <xsl:with-param select="$def" name="def" /> 
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]