RE: [xsl] GUI layout mechanism in XSLT

Subject: RE: [xsl] GUI layout mechanism in XSLT
From: Ilya Boyandin <ilyabo@xxxxxxxxx>
Date: Thu, 6 Jan 2005 16:44:32 +0100
Hello All!

I've had some limited success solving the problem: I made a stylesheet
which performs the necessary transformation suggesting that the input
document is marked with pre-calculated positions of the elements in
the output table.

Would it be possible to improve this stylesheet (or to make a new one)
so that it didn't require pre-calculating?

Here's a sample input with the pre-calculated positions:

<?xml version="1.0" encoding="UTF-8"?>
<layout>
  <hgroup>
    <vgroup>
      <item posx="1" posy="1">1,1</item>
      <item posx="1" posy="2">1,2</item>
    </vgroup>
    <vgroup>
      <item posx="2" posy="1">2,1</item>
      <item posx="2" posy="2">2,2</item>
      <hgroup>
        <item posx="2" posy="3">2,3</item>
        <item posx="3" posy="3">3,3</item>
      </hgroup>
      <item posx="2" posy="4">2,4</item>
    </vgroup>
    <vgroup>
      <item posx="4" posy="1">4,1</item>
      <hgroup>
        <item posx="4" posy="2">4,2</item>
        <item posx="5" posy="2">5,2</item>
      </hgroup>
    </vgroup>
  </hgroup>
</layout>

and the stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:math="http://exslt.org/math";>

  <xsl:output method="html" encoding="UTF-8" />
  <xsl:strip-space elements="*"/>

  <xsl:key name="posx" match="item" use="@posx"/>
  <xsl:key name="posy" match="item" use="@posy"/>
   
  <xsl:template match="layout">
    <table border="1">
    <xsl:call-template name="for-layout-rows">
      <xsl:with-param name="rows" select="math:max(descendant::item/@posy)"/>
      <xsl:with-param name="cols" select="math:max(descendant::item/@posx)"/>
    </xsl:call-template>
    </table>
  </xsl:template>
  
  <xsl:template name="for-layout-rows">
    <xsl:param name="i" select="1"/>
    <xsl:param name="rows"/>
    <xsl:param name="cols"/>
    <xsl:if test="$i &lt;= $rows">
      <tr>
        <xsl:call-template name="for-layout-cols">
          <xsl:with-param name="i" select="$i"/>
          <xsl:with-param name="rows" select="$rows"/>
          <xsl:with-param name="cols" select="$cols"/>
        </xsl:call-template>
      </tr>
      <xsl:call-template name="for-layout-rows">
        <xsl:with-param name="i" select="$i + 1"/>
        <xsl:with-param name="rows" select="$rows"/>
        <xsl:with-param name="cols" select="$cols"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <xsl:template name="for-layout-cols">
    <xsl:param name="i"/>
    <xsl:param name="j" select="1"/>
    <xsl:param name="cols"/>
    <xsl:variable name="rowElems" select="key('posy',string($i))"/>
    <!-- are there more elements in the row? -->
    <xsl:choose>
      <xsl:when test="$rowElems[@posx &gt;= $j]">
        <xsl:choose>
          <xsl:when test="$rowElems[@posx=$j]">
            <td>
              <xsl:apply-templates select="$rowElems[@posx=$j]"/>
            </td>
          </xsl:when>
          <xsl:otherwise><td>&#160;</td></xsl:otherwise>
        </xsl:choose>
        <xsl:call-template name="for-layout-cols">
          <xsl:with-param name="i" select="$i"/>
          <xsl:with-param name="j" select="$j + 1"/>
          <xsl:with-param name="cols" select="$cols"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$cols &gt;= $j">
        <!-- generate the last cell in the row -->
        <td>
          <xsl:attribute name="colspan">
            <xsl:value-of select="$cols - $j + 1"/>
          </xsl:attribute>
          &#160;
        </td>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>


Thanks!
Ilya

-----Original Message-----
From:     Ilya Boyandin <ilyabo@xxxxxxxxx>
Sent:     Wed, 5 Jan 2005 11:49:39 +0100
To:       xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject:  [xsl] GUI layout mechanism in XSLT

Hello All!

I'm trying to implement a simple GUI layout mechanism with XSLT
without much success for now. The problem is that the task requires to
produce an output tree, which structure differs significantly from the
original tree, and in which the elements are likely to be presented in
a different order.

Here's the problem description:

The input is a GUI elements tree. Elements are contained in horizontal
or vertical groups. Naturally, groups can contain other groups. For
instance:

<hgroup>
<vgroup>
  <item>A1</item>
  <item>A2</item>
</vgroup>
<vgroup>
  <item>B1</item>
  <item>B2</item>
  <hgroup>
    <item>B3</item>
    <item>C3</item>
  </hgroup>
</vgroup>
</hgroup>

The output must be one plain table (without nested tables!) in which
the elements are layed out the same as in the input tree. So for the
input tree above the output should be something like this:

<table>
<tr>
  <td>A1</td>
  <td colspan="2">B1</td>
</tr>
<tr>
  <td>A2</td>
  <td colspan="2">B2</td>
</tr>
<tr>
  <td> </td>
  <td>B3</td>
  <td>C3</td>
</tr>
</table>

As I am a newbie, I don't see an obvious solution. I'd be very
thankful if somebody could give me a hint or in the worst case make it
clear that the problem cannot be solved with XSLT alone.

Thank you!
Ilya

Current Thread