xsl-list
[Top] [All Lists]

Plain text wrapped multiple columns

2003-01-09 16:39:51
I need to convert XML into fixed width plain text output in multiple
columns.

<Example>
        <Text>Hello World</Text>
        <Text>from New Zealand</Text>
</Example>

Page width 16

Hello   from New
World   Zealand

I have the wrapping sorted but now trying to add multiple columns in is
causing me grief. Any pointers would be much appreciated. The problem I see
coming is $rest will be a result tree fragment and I won't be able to use
position() on to continue the recursion.

Options that come to mind:

* Can it be done with Formatting Objects? I haven't touched this to date
* Start by converting everything to a pipe delimited string and work through
that
* Preform a double pass, output of the first will be xml with each wrapped
line a separate element and second to form the text columns

Thanks for your thoughts, Peter

<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

        <xsl:import href="selecticaLib.xsl"/>
        <xsl:output method="text"/>

        <xsl:param name="width"/>

        <xsl:template match="/Example">
                <xsl:call-template name="column">
                        <xsl:with-param name="columns" select="Text"/>
                </xsl:call-template>
        </xsl:template>

        <xsl:template name="column">
                <xsl:param name="columns"/>
                <xsl:variable name="size" select="$width div
count($columns)"/>
                <xsl:call-template name="wrap">
                        <xsl:with-param name="size" select="$size"/>
                        <xsl:with-param name="remainder" select="$size"/>
                        <xsl:with-param name="text" select="$columns[1]"/>
                        <xsl:with-param name="rest"
select="$columns[position() != 1]"/>
                </xsl:call-template>
        </xsl:template>

        <xsl:template name="wrap">
                <xsl:param name="size"/>
                <xsl:param name="remainder"/>
                <xsl:param name="text"/>
                <xsl:param name="rest"/>

                <xsl:variable name="MINIMUM_WIDTH" select="3"/> <!-- Needed
so minimum hyphenating doesn't fail -->
                
                <!-- Text remaining to process -->
                <xsl:if test="$text and $size &gt;= $MINIMUM_WIDTH">
                        <xsl:variable name="beforeSpace"
select="substring-before($text, ' ')"/>
                        <xsl:variable name="word">
                                <xsl:if test="$beforeSpace">
                                        <xsl:value-of
select="$beforeSpace"/>
                                </xsl:if>
                                <xsl:if test="not($beforeSpace)">
                                        <xsl:value-of select="$text"/>
                                </xsl:if>
                        </xsl:variable>
                        <xsl:variable name="length"
select="string-length($word)"/>
                        <xsl:variable name="space" select="$remainder !=
$size"/>

                        <!-- Hyphenate words bigger than the column width
-->
                        <xsl:if test="$length &gt; $size and $remainder
&gt;= $MINIMUM_WIDTH"> <!-- Only if there is enough space to bother starting
-->
                                <xsl:if test="$space">
                                        <xsl:text> </xsl:text>
                                </xsl:if>
                                <xsl:value-of select="substring($word, 1,
$remainder - 1 - $space)"/>

                                <xsl:text>-&#xA;</xsl:text>
                                <xsl:call-template name="wrap">
                                        <xsl:with-param name="size"
select="$size"/>
                                        <xsl:with-param name="remainder"
select="$size"/>
                                        <xsl:with-param name="text"
select="substring($text, $remainder - $space)"/>
                                </xsl:call-template>
                        </xsl:if>
                        
                        <!-- Words will fit within the column -->
                        <xsl:if test="$length &lt;= $size or $remainder &lt;
$MINIMUM_WIDTH">
                        
                                <!-- Move to a new column -->
                                <xsl:if test="$length &gt; $remainder -
$space">
                                        <xsl:text>&#xA;</xsl:text>
                                        <xsl:call-template name="wrap">
                                                <xsl:with-param name="size"
select="$size"/>
                                                <xsl:with-param
name="remainder" select="$size"/>
                                                <xsl:with-param name="text"
select="$text"/>
                                                <xsl:with-param name="rest"
select="$rest"/>
                                        </xsl:call-template>
                                </xsl:if>
        
                                <!-- Append word to existing line -->
                                <xsl:if test="$length &lt;= $remainder -
$space">
                                        <xsl:if test="$space">
                                                <xsl:text> </xsl:text>
                                        </xsl:if>
                                        <xsl:value-of select="$word"/>
                                        <xsl:call-template name="wrap">
                                                <xsl:with-param name="size"
select="$size"/>
                                                <xsl:with-param
name="remainder" select="$remainder - $length"/>
                                                <xsl:with-param name="text"
select="substring($text, $length + 2)"/>
                                                <xsl:with-param name="rest"
select="$rest"/>
                                        </xsl:call-template>
                                </xsl:if>
                        </xsl:if>

                </xsl:if>
        </xsl:template>

</xsl:transform>

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



<Prev in Thread] Current Thread [Next in Thread>
  • Plain text wrapped multiple columns, Peter Van de Water <=