Formatting of plain text output

Oki...I got an issue here which I'm having greate difficulties to solv. I would like to dynamically generate a XSL that should give me formatted text as plain text. Example on desired output:

This is a message in plain text.

Column1    Column2              Column3
Data1       DataDataData 2     Data3

Regards
Mr.X

So I need to define the width of the columns at runtime as the column name/data content will differ in each instanse.
I got a XSL, which handles the ordinary text perfectly, but when I want to formatt text in a table style everything gets messy. I would like to add some functionality to my exsisting XSL, which makes it possible to determine the maximum column width to be used to align the text correctly.

I desperately need some help on this one!!
Thanks in advance!
[981 byte] By [hubba09] at [2007-11-19 7:43:21]
# 1 Re: Formatting of plain text output
If you want help with this you have to provide significantly more details about what you are trying to do. Your above message doesn't provide one bit of usefull information. And you seem very confused about what you are doing, in the fist half of your message you talk of dynamically creating xsl's while in the second have you speak of enhancing an exsisting stylesheet.

Show us what your input data looks like, what you have done so far, and explain in detail what problmes you are having. And please be alot more specific.
khp at 2007-11-10 3:27:38 >
# 2 Re: Formatting of plain text output
Alright...I'll elaborate a bit more on my issue.
The code suppiled underneath gives me the result I have today, which makes the text hard to read as the formatting is pretty poor.

I need to display the output in plain text, and therefore I'll have to add some kind of formatting handling in the xsl in order to be able to display something similar to a table.

The xml provided may contain one or more rows. That means I'll have to adjust the column width accordingly to get a readable output.
Desired result:

alert_media description printer status user_id user_name
M guest DEFAULT N GUEST GUESTMAN
E hubba DEFAULT S hubba HUBBA09

So my real question here is how could I use xsl to measure the width of the columns and adding blank spaces in order to get a aligned and readable output in plain text?

XML file:

<xml>
<data>
<row alert_media="M"
bflag="29"
date_from="01.01.1901"
date_to="20991231 23:59:00"
def_client=""
description="guest"
expiration="01.01.1900"
language="EN"
last_device=""
last_update="28.12.2004"
ldap_pointer=""
ldap_type=""
printer="DEFAULT"
priority_no="8"
status="N"
terminal=""
time_from="0"
time_to="0"
user_id="GUEST"
user_name="GUESTMAN"
user_stamp=""
agrtid="3"/>
</data>
</xml>

XSL file

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" media-type="text/plain"/>
<xsl:variable name="pad1" select="' '"/>

<xsl:template match="/">
<xsl:text><![CDATA[alert_media]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[description]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[printer]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[status]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[user_id]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[user_name]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:for-each select="//data/row">
<xsl:text> </xsl:text>
<xsl:value-of select="@alert_media"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@description"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@printer"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@status"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@user_id"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@user_name"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

I'll have to do this dynamically as both the XML and the XSL is created at runtime and they will contain different data depending on user input.

I hope this information will make it easier to understand my problem...

Any help and hints will be greately appreciated!
hubba09 at 2007-11-10 3:28:32 >
# 3 Re: Formatting of plain text output
So my real question here is how could I use xsl to measure the width of the columns and adding blank spaces in order to get a aligned and readable output in plain text?

These are hard problems in xsl. And I'am running out of time for today, so I can't write out the code for you now, a quick explanation of how I would solve it.

First getting the length of the longest string, you can get the length of a string using the string-length() function, getting the largets value in a set of values is more difficult because there is no max function. You can do it with a for-each on the set of elements, perhaps with a sort on string-length and selecting the first element of the result, you might wrap this in a named template for easy use.

As for adding a variable amount of spaces to a string that is also a little bothersome, due to the fact you can't have any true variables in XSL, it can be done using recursion in a named template, adding one space at a time, and subtracting on from a argument you pass along. (note: this can be speeded up using a logarithmic approach)

I'll have to do this dynamically as both the XML and the XSL is created at runtime and they will contain different data depending on user input.

As far as I can't tell you have not shown me anything to support this position, so I can't really make any usefull comments on it.
khp at 2007-11-10 3:29:42 >
# 4 Re: Formatting of plain text output
Found time for a more elaborate response, here's a named template for adding space, and a modified version of your root template that uses it for the first collum in your table, should be aimple job to do the same for the other collumns

<xsl:template name="addspace">
<xsl:param name="space"/>
<xsl:if test="$space>0">
<xsl:text> </xsl:text>
<xsl:call-template name="addspace">
<xsl:with-param name="space" select="$space - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>

<xsl:template match="/">
<xsl:variable name="alertlength">
<xsl:for-each select="//data/row/@alert_media">
<xsl:sort select="string-length(text())"/>
<xsl:if test="position()=1">
<xsl:choose>
<xsl:when test="string-length(text())>string-length('alert_media')">
<xsl:value-of select="number(string-length(text())+1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string-length('alert_media ')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:variable>

<xsl:text><![CDATA[alert_media]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[description]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[printer]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[status]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[user_id]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:text><![CDATA[user_name]]></xsl:text>
<xsl:text> </xsl:text>
<xsl:for-each select="//data/row">
<xsl:text> </xsl:text>
<xsl:value-of select="@alert_media"/>
<xsl:call-template name="add-space">
<xsl:with-param name="space" select="number($alertlength) - stringlength(@alert_media)"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:value-of select="@description"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@printer"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@status"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@user_id"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@user_name"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
khp at 2007-11-10 3:30:36 >
# 5 Re: Formatting of plain text output
Thanks a lot for your help!

Finally got it working and the formatting looks pretty nice, so it was just what I was looking for!

Your help is greatly appreciated!!
hubba09 at 2007-11-10 3:31:38 >