Dynamic table rows?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Dynamic table rows?

Nathan Maves
Here is what I have so far.  What I need is a have a two column table  
based on a list of category elements.  So in a list  
<Cat1,Cat2,Cat3,Cat4> I want a table like.

Cat1 ----- Cat2
Cat3 ----- Cat4

The logic seems right to me but I get the following error.

javax.xml.transform.TransformerConfigurationException:  
javax.xml.transform.TransformerConfigurationException:  
javax.xml.transform.TransformerException:  
org.xml.sax.SAXParseException: The element type "fo:table-row" must  
be terminated by the matching end-tag "</fo:table-row>".


<fo:table-body>
         <xsl:for-each select="category">

             <xsl:if test="(position() mod 2) = 1">
                 <fo:table-row>
             </xsl:if>

               <fo:table-cell>
                 <fo:block>

                     Poisition <xsl:value-of select="position()"/>
                     Last <xsl:value-of select="last()"/>
                   <xsl:apply-templates select="."/>
                 </fo:block>
               </fo:table-cell>

             <xsl:if test="((position() mod 2) = 0) or (position() =  
last())">
                 </fo:table-row>
              </xsl:if>

         </xsl:for-each>
       </fo:table-body>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Dynamic table rows?

JBryant
Hi, Nathan,

XSL documents are XML documents, so they must be well-formed. Thus, you
can't do:

<xsl:if test="(position() mod 2) = 1">
  <fo:table-row>
</xsl:if>

You must do:

<xsl:if test="(position() mod 2) = 1">
  <fo:table-row>
  </fo:table-row>
</xsl:if>

The trouble is, of course, that that's not what you want.

To get each row to have two cells, you need to back up a notch to whatever
template calls the row-making template and use the mod trick in the
apply-templates (or for-each or whatever) statement you have there.

So, for example, if I have input data like this:

<x>
 <y>V1</y>
 <y>V2</y>
 <y>V3</y>
 <y>V4</y>
</x>

And I want my <y> values two to a row in a table, I could do:

  <xsl:template match="x">
    <fo:table>
      <fo:table-column column-width="3.25in"/>
      <fo:table-column column-width="3.25in"/>
      <fo:table-body>
        <xsl:apply-templates select="y[position() mod 2 = 1]"/>
      </fo:table-body>
    </fo:table>
  </xsl:template>
 
  <xsl:template match="y[following-sibling::*[1]/self::y]">
    <fo:table-row>
      <fo:table-cell>
        <fo:block><xsl:value-of select="."/></fo:block>
      </fo:table-cell>
      <fo:table-cell>
        <fo:block><xsl:value-of
select="following-sibling::y[1]"/></fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

  <xsl:template match="y[not(following-sibling::*[1]/self::y)]">
    <fo:table-row>
      <fo:table-cell number-columns-spanned="2">
        <fo:block><xsl:value-of select="."/></fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

match="y[following-sibling::*[1]/self::y]" means, in English: match the y
nodes where the next sibling is also a y node. The template with the not()
function means the reverse, of course. You can't just just
match="y[following-sibling::y] because you might have another set of y
nodes to render in a different table later on (or maybe not, since I don't
know your data). Also, if you ALWAYS have an even number of nodes, you can
just use the first template and change it to match="y".

I just tested those three templates with 4 and 5 y values and got the
results I expected.

Let us know if you have other troubles. Also, this was a generic XSL
question rather than a FOP question. The Mulberry XSL list will get you
more help for this kind of thing (I hang out there, too, for what it's
worth). That list is at http://www.mulberrytech.com/xsl/xsl-list/

Jay Bryant
Bryant Communication Services
(presently consulting at Synergistic Solution Technologies)




Nathan Maves <[hidden email]>
05/26/2005 01:54 PM
Please respond to
[hidden email]


To
[hidden email]
cc

Subject
Dynamic table rows?






Here is what I have so far.  What I need is a have a two column table
based on a list of category elements.  So in a list
<Cat1,Cat2,Cat3,Cat4> I want a table like.

Cat1 ----- Cat2
Cat3 ----- Cat4

The logic seems right to me but I get the following error.

javax.xml.transform.TransformerConfigurationException:
javax.xml.transform.TransformerConfigurationException:
javax.xml.transform.TransformerException:
org.xml.sax.SAXParseException: The element type "fo:table-row" must
be terminated by the matching end-tag "</fo:table-row>".


<fo:table-body>
         <xsl:for-each select="category">

             <xsl:if test="(position() mod 2) = 1">
                 <fo:table-row>
             </xsl:if>

               <fo:table-cell>
                 <fo:block>

                     Poisition <xsl:value-of select="position()"/>
                     Last <xsl:value-of select="last()"/>
                   <xsl:apply-templates select="."/>
                 </fo:block>
               </fo:table-cell>

             <xsl:if test="((position() mod 2) = 0) or (position() =
last())">
                 </fo:table-row>
              </xsl:if>

         </xsl:for-each>
       </fo:table-body>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]




---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Dynamic table rows?

Nathan Maves
Thanks Jay!

In the mean time I did find this example which seems to work as  
well.  Same idea as yours.

     <fo:table-body>
         <xsl:for-each select="category[position() mod 2 = 1]">
           <fo:table-row>
             <xsl:for-each select=". | following-sibling::category[1]">
               <fo:table-cell><xsl:apply-templates select="." /></
fo:table-cell>
             </xsl:for-each>
           </fo:table-row>
         </xsl:for-each>
       </fo:table-body>


On May 26, 2005, at 1:44 PM, [hidden email] wrote:

> Hi, Nathan,
>
> XSL documents are XML documents, so they must be well-formed. Thus,  
> you
> can't do:
>
> <xsl:if test="(position() mod 2) = 1">
>   <fo:table-row>
> </xsl:if>
>
> You must do:
>
> <xsl:if test="(position() mod 2) = 1">
>   <fo:table-row>
>   </fo:table-row>
> </xsl:if>
>
> The trouble is, of course, that that's not what you want.
>
> To get each row to have two cells, you need to back up a notch to  
> whatever
> template calls the row-making template and use the mod trick in the
> apply-templates (or for-each or whatever) statement you have there.
>
> So, for example, if I have input data like this:
>
> <x>
>  <y>V1</y>
>  <y>V2</y>
>  <y>V3</y>
>  <y>V4</y>
> </x>
>
> And I want my <y> values two to a row in a table, I could do:
>
>   <xsl:template match="x">
>     <fo:table>
>       <fo:table-column column-width="3.25in"/>
>       <fo:table-column column-width="3.25in"/>
>       <fo:table-body>
>         <xsl:apply-templates select="y[position() mod 2 = 1]"/>
>       </fo:table-body>
>     </fo:table>
>   </xsl:template>
>
>   <xsl:template match="y[following-sibling::*[1]/self::y]">
>     <fo:table-row>
>       <fo:table-cell>
>         <fo:block><xsl:value-of select="."/></fo:block>
>       </fo:table-cell>
>       <fo:table-cell>
>         <fo:block><xsl:value-of
> select="following-sibling::y[1]"/></fo:block>
>       </fo:table-cell>
>     </fo:table-row>
>   </xsl:template>
>
>   <xsl:template match="y[not(following-sibling::*[1]/self::y)]">
>     <fo:table-row>
>       <fo:table-cell number-columns-spanned="2">
>         <fo:block><xsl:value-of select="."/></fo:block>
>       </fo:table-cell>
>     </fo:table-row>
>   </xsl:template>
>
> match="y[following-sibling::*[1]/self::y]" means, in English: match  
> the y
> nodes where the next sibling is also a y node. The template with  
> the not()
> function means the reverse, of course. You can't just just
> match="y[following-sibling::y] because you might have another set of y
> nodes to render in a different table later on (or maybe not, since  
> I don't
> know your data). Also, if you ALWAYS have an even number of nodes,  
> you can
> just use the first template and change it to match="y".
>
> I just tested those three templates with 4 and 5 y values and got the
> results I expected.
>
> Let us know if you have other troubles. Also, this was a generic XSL
> question rather than a FOP question. The Mulberry XSL list will get  
> you
> more help for this kind of thing (I hang out there, too, for what it's
> worth). That list is at http://www.mulberrytech.com/xsl/xsl-list/
>
> Jay Bryant
> Bryant Communication Services
> (presently consulting at Synergistic Solution Technologies)
>
>
>
>
> Nathan Maves <[hidden email]>
> 05/26/2005 01:54 PM
> Please respond to
> [hidden email]
>
>
> To
> [hidden email]
> cc
>
> Subject
> Dynamic table rows?
>
>
>
>
>
>
> Here is what I have so far.  What I need is a have a two column table
> based on a list of category elements.  So in a list
> <Cat1,Cat2,Cat3,Cat4> I want a table like.
>
> Cat1 ----- Cat2
> Cat3 ----- Cat4
>
> The logic seems right to me but I get the following error.
>
> javax.xml.transform.TransformerConfigurationException:
> javax.xml.transform.TransformerConfigurationException:
> javax.xml.transform.TransformerException:
> org.xml.sax.SAXParseException: The element type "fo:table-row" must
> be terminated by the matching end-tag "</fo:table-row>".
>
>
> <fo:table-body>
>          <xsl:for-each select="category">
>
>              <xsl:if test="(position() mod 2) = 1">
>                  <fo:table-row>
>              </xsl:if>
>
>                <fo:table-cell>
>                  <fo:block>
>
>                      Poisition <xsl:value-of select="position()"/>
>                      Last <xsl:value-of select="last()"/>
>                    <xsl:apply-templates select="."/>
>                  </fo:block>
>                </fo:table-cell>
>
>              <xsl:if test="((position() mod 2) = 0) or (position() =
> last())">
>                  </fo:table-row>
>               </xsl:if>
>
>          </xsl:for-each>
>        </fo:table-body>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]