This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: String parsing, node creation
- From: Mike Brown <mike at skew dot org>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Tue, 26 Feb 2002 14:35:46 -0700 (MST)
- Subject: Re: [xsl] String parsing, node creation
- Reply-to: xsl-list at lists dot mulberrytech dot com
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,' ')">
<xsl:call-template name="justify">
<xsl:with-param name="width" select="$maxwidth"/>
<xsl:with-param name="txt" select="substring-before($text,' ')"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:call-template name="wrap-multiline">
<xsl:with-param name="text" select="substring-after($text,' ')"/>
</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 < 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),' ')" />
<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