|
|
|
date: Sat, 19 Apr 2008 15:41:01 -0700,
group: microsoft.public.xsl
back
Re: Table XSL Question - Martin Honnen?
Brian wrote:
> I have a variable number of elements in my XML... I want to display them in
> a table with no more than 4 columns. So if I have 6 elements, I'll have two
> rows of cells, 4 cells across with only 6 populated.
Assuming you have the following input XML:
<root>
<foo>1, 1</foo>
<foo>1, 2</foo>
<foo>1, 3</foo>
<foo>1, 4</foo>
<foo>2, 1</foo>
<foo>2, 2</foo>
<foo>2, 3</foo>
<foo>2, 4</foo>
<foo>3, 1</foo>
<foo>3, 2</foo>
</root>
then this XSLT 1.0 stylesheet
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="cols" select="4"/>
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html lang="en">
<head>
<title>Table example</title>
</head>
<body>
<xsl:apply-templates select="root"/>
</body>
</html>
</xsl:template>
<xsl:template match="root">
<table border="1">
<tbody>
<xsl:apply-templates select="foo[position() mod $cols = 1]"
mode="row"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="foo" mode="row">
<tr>
<xsl:variable name="siblings"
select="following-sibling::foo[position() < $cols]"/>
<xsl:apply-templates select=". | $siblings" mode="cell"/>
<xsl:if test="count($siblings) < ($cols - 1)">
<xsl:call-template name="make-empty-cells">
<xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
</xsl:call-template>
</xsl:if>
</tr>
</xsl:template>
<xsl:template match="foo" mode="cell">
<td>
<xsl:apply-templates/>
</td>
</xsl:template>
<xsl:template name="make-empty-cells">
<xsl:param name="n"/>
<xsl:if test="$n > 0">
<td></td>
<xsl:call-template name="make-empty-cells">
<xsl:with-param name="n" select="$n - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
produces this HTML output:
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Table example</title>
</head>
<body>
<table border="1">
<tbody>
<tr>
<td>1, 1</td>
<td>1, 2</td>
<td>1, 3</td>
<td>1, 4</td>
</tr>
<tr>
<td>2, 1</td>
<td>2, 2</td>
<td>2, 3</td>
<td>2, 4</td>
</tr>
<tr>
<td>3, 1</td>
<td>3, 2</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
With XSLT 2.0 it is easier:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:param name="cols" select="4"/>
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html lang="en">
<head>
<title>Table example</title>
</head>
<body>
<xsl:apply-templates select="root"/>
</body>
</html>
</xsl:template>
<xsl:template match="root">
<table border="1">
<tbody>
<xsl:for-each-group select="foo" group-by="(position() - 1)
idiv $cols">
<tr>
<xsl:apply-templates select="current-group()" mode="cell"/>
<xsl:for-each select="1 to ($cols - count(current-group()))">
<td></td>
</xsl:for-each>
</tr>
</xsl:for-each-group>
</tbody>
</table>
</xsl:template>
<xsl:template match="foo" mode="cell">
<td>
<xsl:apply-templates/>
</td>
</xsl:template>
</xsl:stylesheet>
--
Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
date: Sun, 20 Apr 2008 14:30:07 +0200
author: Martin Honnen
Re: Table XSL Question - Martin Honnen?
Thanks for the input... my xml isn't quite that simple... but I'm tryin to
make your transform apply. But I'm stuck...
I keep getting the error "Unexpected Child". I'm using XML Spy (2006 Pro)
to perform the transform.
The list of nodes is in the position shown here:
<root>
<Element></Element>
<Element2>
<listparent>
<ListItem1/>
<ListItem2/>
<ListItem3/>
.
.
.
</listparent>
</Element2>
<Element3>
.....
</Element3>
Thanks for your guidance.
"Martin Honnen" wrote:
> Brian wrote:
>
> > I have a variable number of elements in my XML... I want to display them in
> > a table with no more than 4 columns. So if I have 6 elements, I'll have two
> > rows of cells, 4 cells across with only 6 populated.
>
> Assuming you have the following input XML:
>
> <root>
> <foo>1, 1</foo>
> <foo>1, 2</foo>
> <foo>1, 3</foo>
> <foo>1, 4</foo>
> <foo>2, 1</foo>
> <foo>2, 2</foo>
> <foo>2, 3</foo>
> <foo>2, 4</foo>
> <foo>3, 1</foo>
> <foo>3, 2</foo>
> </root>
>
> then this XSLT 1.0 stylesheet
>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xsl:param name="cols" select="4"/>
>
> <xsl:output method="html" indent="yes"/>
>
> <xsl:template match="/">
> <html lang="en">
> <head>
> <title>Table example</title>
> </head>
> <body>
> <xsl:apply-templates select="root"/>
> </body>
> </html>
> </xsl:template>
>
> <xsl:template match="root">
> <table border="1">
> <tbody>
> <xsl:apply-templates select="foo[position() mod $cols = 1]"
> mode="row"/>
> </tbody>
> </table>
> </xsl:template>
>
> <xsl:template match="foo" mode="row">
> <tr>
> <xsl:variable name="siblings"
> select="following-sibling::foo[position() < $cols]"/>
> <xsl:apply-templates select=". | $siblings" mode="cell"/>
> <xsl:if test="count($siblings) < ($cols - 1)">
> <xsl:call-template name="make-empty-cells">
> <xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
> </xsl:call-template>
> </xsl:if>
> </tr>
> </xsl:template>
>
> <xsl:template match="foo" mode="cell">
> <td>
> <xsl:apply-templates/>
> </td>
> </xsl:template>
>
> <xsl:template name="make-empty-cells">
> <xsl:param name="n"/>
> <xsl:if test="$n > 0">
> <td></td>
> <xsl:call-template name="make-empty-cells">
> <xsl:with-param name="n" select="$n - 1"/>
> </xsl:call-template>
> </xsl:if>
> </xsl:template>
>
> </xsl:stylesheet>
>
> produces this HTML output:
>
> <html lang="en">
> <head>
> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
>
> <title>Table example</title>
> </head>
> <body>
> <table border="1">
> <tbody>
> <tr>
> <td>1, 1</td>
> <td>1, 2</td>
> <td>1, 3</td>
> <td>1, 4</td>
> </tr>
> <tr>
> <td>2, 1</td>
> <td>2, 2</td>
> <td>2, 3</td>
> <td>2, 4</td>
> </tr>
> <tr>
> <td>3, 1</td>
> <td>3, 2</td>
> <td></td>
> <td></td>
> </tr>
> </tbody>
> </table>
> </body>
> </html>
>
>
> With XSLT 2.0 it is easier:
>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="2.0">
>
> <xsl:param name="cols" select="4"/>
>
> <xsl:output method="html" indent="yes"/>
>
> <xsl:template match="/">
> <html lang="en">
> <head>
> <title>Table example</title>
> </head>
> <body>
> <xsl:apply-templates select="root"/>
> </body>
> </html>
> </xsl:template>
>
> <xsl:template match="root">
> <table border="1">
> <tbody>
> <xsl:for-each-group select="foo" group-by="(position() - 1)
> idiv $cols">
> <tr>
> <xsl:apply-templates select="current-group()" mode="cell"/>
> <xsl:for-each select="1 to ($cols - count(current-group()))">
> <td></td>
> </xsl:for-each>
> </tr>
> </xsl:for-each-group>
> </tbody>
> </table>
> </xsl:template>
>
> <xsl:template match="foo" mode="cell">
> <td>
> <xsl:apply-templates/>
> </td>
> </xsl:template>
>
> </xsl:stylesheet>
>
>
> --
>
> Martin Honnen --- MVP XML
> http://JavaScript.FAQTs.com/
>
date: Sun, 20 Apr 2008 09:06:00 -0700
author: Brian
|
|