[xsl] table creation with element repetition

Subject: [xsl] table creation with element repetition
From: Fantuzzi Alessandro <a.fantuzzi@xxxxxxxxxx>
Date: Fri, 30 Apr 2004 13:45:18 +0200
hi,
I am trying to create a two column table in a pdf starting from a list
of products. 
The point is that each product has to be repeated n times as indicated
by the attribute "copies" of the "product" element.

sample xml

<?xml version="1.0" encoding="UTF-8"?>
<doc name="products print" >
  <products_to_print>
    <product copies="1">
      <description>product 1</description>
    </product>
    <product copies="2">
      <description>product 2</description>
    </product>
    <product copies="2">
      <description>product 3</description>
    </product>
  </products_to_print>
</doc>

this is the tree that should be created starting from the xml above

<fo:table-column column-width="73mm"/>
<fo:table-column column-width="73mm"/>

<fo:table-body>
  <fo:table-row>
    <fo:table-cell>
      <fo:block>product 1</fo:block>
    </fo:table-cell>
    <fo:table-cell>
      <fo:block>product 2</fo:block>
    </fo:table-cell>              
  </fo:table-row>
  <fo:table-row>
    <fo:table-cell>
      <fo:block>product 2</fo:block>
    </fo:table-cell>
    <fo:table-cell>
      <fo:block>product 3</fo:block>
    </fo:table-cell>              
  </fo:table-row>
  <fo:table-row>
    <fo:table-cell>
      <fo:block>product 3</fo:block>
    </fo:table-cell>
    <fo:table-cell>
      <fo:block/>
    </fo:table-cell>              
  </fo:table-row>                        
</fo:table-body>

Any attempt to create a proper template has encountered some xsl
limitation :
impossibility to open and close an element in two separate templates
impossibility to change variable values at runtime.

The first limitation forces me to create two cells within the same
template where I create the rows.
The second limitation makes it impossible to switch to the next product
element from the first column to the second because i cannot increment
the variable indicating the position of the element to process, I also
cannot decrement the number of copies added for a product.

here is a sample xsl containg the recursive template I created
the template is called the first time by another with some parameters

<!-- code omitted -->
<xsl:with-param name="totcopies" select="count(//product/@copies")/>
<xsl:with-param name="iposition" select="1"/>
<xsl:with-param name="product_copies" select="//product[1]/@copies"/>
<!-- code omitted -->

<!-- the template that adds rows to a table -->
<xsl:template name="product_rows">
  <xsl:param name="totcopies">0</xsl:param>
  <xsl:param name="iposition">0</xsl:param>
  <xsl:param name="product_copies" select="0"/>

  <xsl:if test="number($totcopies) >= 1">

    <fo:table-row>

      <xsl:if test="number($totcopies)  &lt; 1">
      <!-- impossible with xsl -->
      <xsl:param name="iposition" select="$iposition + 1" />
      <xsl:param 
        name="product_copies" 
        select="//product[$iposition]/@copies" />
      <!-- impossible with xsl -->
      </xsl:if>

      <!-- first column -->
      <fo:table-cell >
        <fo:block>
          description:
          <xsl:value-of select="//product[$iposition]/descrizione"/>
        </fo:block>
      </fo:table-cell>

      <!-- impossible with xsl -->
      <xsl:param name="product_copies" select="$product_copies - 1" />

      <xsl:if test="number($totcopies)  &lt; 1">
        <!-- impossible with xsl -->
        <xsl:param name="iposition" select="$iposition + 1" />
        <xsl:param 
          name="product_copies" 
          select="//product[$iposition]/@copies" />
        <!-- impossible with xsl -->
      </xsl:if>
      
      <!-- second column -->
      <fo:table-cell>
        <xsl:choose>
          <xsl:when test="number($copietot) - 1  >= 1">
            <fo:block>
              description:
              <xsl:value-of select="//product[$iposition]/descrizione"/>
            </fo:block>
          </xsl:when>
          <!-- empty cell -->
          <xsl:otherwise>
              <fo:block />
            </xsl:otherwise>
          </xsl:choose>
        </fo:table-cell>
      </fo:table-row>

      <!-- impossible with xsl -->
      <xsl:param name="product_copies" select="$product_copies - 1"/>

      <xsl:call-template name="product_rows">
        <xsl:with-param name="totcopies" select="$totcopies - 2"/>
        <xsl:with-param name="iposition" select="$id"/>
        <xsl:with-param name="product_copies" select="$product_copies"/>
      </xsl:call-template>

    </xsl:if>

  </xsl:template>
<!-- code omitted -->


any suggestion appreciated,

ALESSANDRO

Current Thread