 |
| XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

November 25th, 2003, 01:24 PM
|
|
Registered User
|
|
Join Date: Oct 2003
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
xslt looping with tables...
I wonder if anyone can help me. I'm trying to do a simple loop which will loop a certain number of columns and then loop down onto a new row, inside a table.
Easily done in asp, and i've seen it in xslt before, but not understood it, fully. So i was hoping someone might have an example they could just quickly run through and explain what each part does...?
Thanks
|
|

November 26th, 2003, 01:57 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
As I understand, you needn't to do any transformation; all you need is just to output a table. So, if this is true, look what can you do:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="c" select="3"/>
<xsl:param name="r" select="4"/>
<xsl:template match="/">
<xsl:call-template name="output-rows">
<xsl:with-param name="columns" select="$c"/>
<xsl:with-param name="rows" select="$r"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="output-rows">
<xsl:param name="columns"/>
<xsl:param name="rows"/>
<xsl:choose>
<xsl:when test="$rows > 0">
<tr>
<xsl:call-template name="output-columns">
<xsl:with-param name="columns" select="$columns"/>
<xsl:with-param name="rows" select="$rows"/>
</xsl:call-template>
</tr>
<xsl:call-template name="output-rows">
<xsl:with-param name="columns" select="$columns"/>
<xsl:with-param name="rows" select="$rows - 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template name="output-columns">
<xsl:param name="columns"/>
<xsl:param name="rows"/>
<xsl:choose>
<xsl:when test="$columns > 0">
<td>
<xsl:element name="cell">
<xsl:value-of select="concat('[', $r - $rows + 1, ', ', $c - $columns + 1, ']')"/>
</xsl:element>
</td>
<xsl:call-template name="output-columns">
<xsl:with-param name="columns" select="$columns - 1"/>
<xsl:with-param name="rows" select="$rows"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This stylesheet can be applied to any XML document (to itself, for example).
The stylesheet has 2 recursive templates; one to output rows and other to output columns. It's just simulating simple looping construct through recursive structure and nothing more. If you have any concrete question, let me know please.
Regards,
Armen
|
|

November 26th, 2003, 07:24 AM
|
|
Registered User
|
|
Join Date: Oct 2003
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thank you, I understand what's going on as a whole. But I'm not sure I understand what exactly is going on here though...
<xsl:element name="cell">
<xsl:value-of select="concat('[', $r - $rows + 1, ', ', $c - $columns + 1, ']')"/>
</xsl:element>
... As you can tell, I'm very new to xml/xslt. :p
|
|

November 26th, 2003, 08:01 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Quote:
quote:Originally posted by lukemedway_uk
Thank you, I understand what's going on as a whole. But I'm not sure I understand what exactly is going on here though...
<xsl:element name="cell">
<xsl:value-of select="concat('[', $r - $rows + 1, ', ', $c - $columns + 1, ']')"/>
</xsl:element>
... As you can tell, I'm very new to xml/xslt. :p
|
Since the templates decrement the values in each recursive pass, we have to do that(concat('[', $r - $rows + 1, ', ', $c - $columns + 1, ']')) to get values (1,1) (1,2).... (2,1) (2,2)... in this sequence. Otherwise (concat('[', $rows, ', ', $columns, ']')) will give the "opposite" sequence, i.e. (4,3) (4,2) (4,1) (3,3) ...
Regards,
Armen
|
|

December 19th, 2003, 01:53 AM
|
|
Authorized User
|
|
Join Date: Dec 2003
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi Armmarti,
I'm trying to accomplish something similar, except that I need to do data transformation. Here's some example xml:
<products>
<product><title>123</title><price>10</price></product>
<product><title>456</title><price>11</price></product>
<product><title>789</title><price>12</price></product>
<product><title>a</title><price>14</price></product>
<product><title>b</title><price>15</price></product>
<product><title>c</title><price>16</price></product>
</products>
(over 100 records)
I need the output to have 3 columns, like this:
<table><tr><td>Product Title</td><td>Price</td><td>Product Title</td><td>Price</td><td>Product Title</td><td>Price</td></tr>
</table>
Any input would be greatly appreciated.
Thanks!
Quote:
quote:Originally posted by armmarti
As I understand, you needn't to do any transformation; all you need is just to output a table. So, if this is true, look what can you do:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="c" select="3"/>
<xsl:param name="r" select="4"/>
<xsl:template match="/">
<xsl:call-template name="output-rows">
<xsl:with-param name="columns" select="$c"/>
<xsl:with-param name="rows" select="$r"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="output-rows">
<xsl:param name="columns"/>
<xsl:param name="rows"/>
<xsl:choose>
<xsl:when test="$rows > 0">
<tr>
<xsl:call-template name="output-columns">
<xsl:with-param name="columns" select="$columns"/>
<xsl:with-param name="rows" select="$rows"/>
</xsl:call-template>
</tr>
<xsl:call-template name="output-rows">
<xsl:with-param name="columns" select="$columns"/>
<xsl:with-param name="rows" select="$rows - 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template name="output-columns">
<xsl:param name="columns"/>
<xsl:param name="rows"/>
<xsl:choose>
<xsl:when test="$columns > 0">
<td>
<xsl:element name="cell">
<xsl:value-of select="concat('[', $r - $rows + 1, ', ', $c - $columns + 1, ']')"/>
</xsl:element>
</td>
<xsl:call-template name="output-columns">
<xsl:with-param name="columns" select="$columns - 1"/>
<xsl:with-param name="rows" select="$rows"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This stylesheet can be applied to any XML document (to itself, for example).
The stylesheet has 2 recursive templates; one to output rows and other to output columns. It's just simulating simple looping construct through recursive structure and nothing more. If you have any concrete question, let me know please.
Regards,
Armen
|
|
|

December 19th, 2003, 04:48 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi,
Let's clarify what you want: the output you want has more than 3 columns... I guess you mistyped and really you want 2 columns (title and price). Please clarify the point to be able to help you.
Regards,
Armen
|
|

December 19th, 2003, 10:08 AM
|
|
Authorized User
|
|
Join Date: Dec 2003
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Oops, sorry for the typo.
The data makes the table too long when it is in only 2 columns (title, price) so I'd like to make the data go across 3 records per row and then down.
I would like to see a total of 6 columns (title, price, title, price, title, price) or 3 pairs as it scrolls through the records.
Thanks!!!!!
|
|

December 19th, 2003, 02:43 PM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
I've tried to deal with this as much generally as I could [ prior to my free time ;) ].
The stylesheet is general enough.
Any xml document can be rendered as soon as it has this structure (element types are irrelevant):
Code:
<rows>
<row>
<item1>...</item1>
<item2>...</item2>
...
<itemN>...</itemN>
</row>
...
</rows>
Try to play with it. You can pass a parameter "n-big-cols" to the stylesheet to give the number of big-columns (3 in your example).
Enjoyed writing the stylesheet!
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:param name="n-big-cols" select="3"/>
<xsl:variable name="all-items" select="/*/*"/>
<xsl:variable name="n-items" select="count($all-items)"/>
<xsl:variable name="n-rows" select="ceiling($n-items div $n-big-cols)"/>
<xsl:variable name="n-fields" select="count($all-items[1]/*)"/>
<xsl:variable name="first-col-color" select="'#cccccc'" />
<xsl:template match="/">
<html>
<head>
<title/>
</head>
<body>
<table border="1" cellspacing="0">
<tbody>
<tr>
<xsl:call-template name="put-header"/>
</tr>
<xsl:call-template name="put-data"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template name="put-header">
<xsl:param name="idx" select="1"/>
<xsl:if test="$idx <= $n-big-cols">
<xsl:for-each select="$all-items[1]/*">
<th >
<xsl:if test="position() = 1">
<xsl:attribute name="bgcolor"><xsl:value-of select="$first-col-color"/></xsl:attribute>
</xsl:if>
<xsl:value-of select="local-name()"/>
</th>
</xsl:for-each>
<xsl:call-template name="put-header">
<xsl:with-param name="idx" select="$idx + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="put-data">
<xsl:param name="idx" select="1"/>
<xsl:if test="$idx <= $n-rows">
<tr>
<xsl:call-template name="put-item">
<xsl:with-param name="r" select="$idx"/>
<xsl:with-param name="c" select="1"/>
</xsl:call-template>
</tr>
<xsl:call-template name="put-data">
<xsl:with-param name="idx" select="$idx + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="put-item">
<xsl:param name="internal-col-idx" select="0"/>
<xsl:param name="r"/>
<xsl:param name="c"/>
<xsl:if test="$c <= $n-big-cols">
<xsl:variable name="curr-el" select="$all-items[($c - 1) * $n-rows + $r]/*[$internal-col-idx + 1]"/>
<xsl:choose>
<xsl:when test="not($curr-el)">
<xsl:call-template name="fill-gap">
<xsl:with-param name="cnt" select="$n-fields"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:if test="not($curr-el/preceding-sibling::*)">
<xsl:attribute name="bgcolor"><xsl:value-of select="$first-col-color"/></xsl:attribute>
</xsl:if>
<xsl:value-of select="$curr-el"/>
</td>
<xsl:call-template name="put-item">
<xsl:with-param name="internal-col-idx" select="($internal-col-idx + 1) mod $n-fields"/>
<xsl:with-param name="r" select="$r"/>
<xsl:with-param name="c" select="$c + number(not($curr-el/following-sibling::*))"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template name="fill-gap">
<xsl:param name="cnt"/>
<xsl:if test="$cnt > 0">
<td>
<xsl:if test="$cnt = $n-fields">
<xsl:attribute name="bgcolor">
<xsl:value-of select="$first-col-color"/>
</xsl:attribute>
</xsl:if>
#xA0;
</td>
<xsl:call-template name="fill-gap">
<xsl:with-param name="cnt" select="$cnt - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Regards,
Armen
|
|

December 19th, 2003, 02:47 PM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Again all ampersands disappeared for character references...
Add the ampersand symbol before '#xA0;'
|
|

December 19th, 2003, 09:43 PM
|
|
Authorized User
|
|
Join Date: Dec 2003
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Wow!
You have out done yourself! Thank you immensely for all of your help.
I am wondering if you would know how to choose which columns of data that you want to display. I don't want to display all of the columns of data, just a few of them.
I could write a stylesheet to transform the xml to another xml file that only has the fields that I want...but could this stylesheet be adapted to be able to choose which fields you want to display?
Again, thanks for your help!!!!
|
|
 |