Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > looping templates

Reply
Thread Tools

looping templates

 
 
Ruthless
Guest
Posts: n/a
 
      12-29-2003
Hello.

I've got a simple XML:

<?xml version="1.0" encoding="iso-8859-2"?>
<?xml-stylesheet type="text/xsl" href="4.xsl"?>

<struct>

<node level="1" no="1">

<node level="2" no="2" />
<node level="2" no="3" />
<node level="2" no="4" />
</node>

<node level="1" no="5">

<node level="2" no="6" />
<node level="2" no="7" />
<node level="2" no="8" />
</node>

</struct>

and i want to display all the levels starting from 1 to 2

I've got my xslt sth like this:

<?xml version="1.0" encoding="ISO-8859-2" ?>
<xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xslutput method="html"/>

<xsl:template match="/">

<html>
<body>

<table align="center" border="1">
<tr>
<th>Name</th><th>No.</th><th>Level</th>
</tr>

<xsl:for-each select="//node">
<xsl:sort select="@level"/>

<xsl:if test="@level='1'">
<tr>
<td align="center"><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="@no"/></td>
<td><xsl:value-of select="@level"/></td>
</tr>
</xsl:if>
</xsl:for-each>

</table>

<!-- now goes level 2-->

<table align="center" border="1">
<tr>
<th>Name</th><th>No.</th><th>Level</th>
</tr>

<xsl:for-each select="//node">
<xsl:sort select="@level"/>

<xsl:if test="@level='2'">
<tr>
<td align="center"><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="@no"/></td>
<td><xsl:value-of select="@level"/></td>
</tr>
</xsl:if>
</xsl:for-each>

</table>
</body>
</html>

</xsl:template>

</xsl:stylesheet>

It works fine but it's useless when there would be more then 2 levels - how
can i loop this template to go through all the levels - each level has a new
table(just like above)

and second thing how can i count node with e.g. attributes level="2"?

I've tried sth like this:
<xsl:template match="/">
<xsl:variable name="ile" select="count(//node@level='2')" />
</xsl:template>

and then:

<b><xsl:value-of select="$ile"/></b>

but it's wrong and i've got warning msg.

thanks in advance
greetings R


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.554 / Virus Database: 346 - Release Date: 03-12-20


 
Reply With Quote
 
 
 
 
Dimitre Novatchev
Guest
Posts: n/a
 
      12-30-2003
The way to do this is the following:

This transformation:

<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="*[node]">
<table align="center" border="1">
<tr>
<th>Name</th><th>No.</th><th>Level</th>
<xsl:apply-templates select="node" mode="display"/>
</tr>
</table>
<br />
<br />
<xsl:apply-templates select="node"/>
</xsl:template>

<xsl:template match="node" mode="display">
<tr>
<td align="center"><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="@no"/></td>
<td><xsl:value-of select="@level"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>

When applied on this source.xml:

<struct>
<node level="1" no="1">
<node level="2" no="2" />
<node level="2" no="3">
<node level="3" no="4"/>
</node>
<node level="2" no="5" />
</node>
<node level="1" no="6">
<node level="2" no="7">
<node level="3" no="8"/>
<node level="3" no="9"/>
</node>
<node level="2" no="10" />
<node level="2" no="11" />
</node>
</struct>

Produces this output (as displayed in the browser):

Name No. Level

node 1 1

node 6 1




Name No. Level

node 2 2

node 3 2

node 5 2




Name No. Level

node 4 3




Name No. Level

node 7 2

node 10 2

node 11 2




Name No. Level

node 8 3

node 9 3


However you want all nodes belonging to the same level to be displayed in a
single table.

In this case this transformation:


<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="kByLevel" match="node" use="@level"/>

<xsl:variable name="vMinMaxLevel">
<xsl:for-each
select="//node[generate-id()
=
generate-id(key('kByLevel', @level)[1])
]">
<xsl:sort select="@level" data-type="number"/>

<xsl:if test="position() = 1 or position() = last()">
<xsl:value-of select="@level"/>
<xsl:if test="position() = 1">|</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:variable>

<xsl:template match="/">
<xsl:call-template name="displayH">
<xsl:with-param name="pLevel"
select="substring-before($vMinMaxLevel, '|')"/>
<xsl:with-param name="pMaxLevel"
select="substring-after($vMinMaxLevel, '|')"/>

</xsl:call-template>
</xsl:template>

<xsl:template name="displayH">
<xslaram name="pLevel" select="1"/>
<xslaram name="pMaxLevel" select="1"/>

<xsl:variable name="vThisLevel"
select="key('kByLevel', $pLevel)"/>

<xsl:if test="$pLevel &lt;= $pMaxLevel
and $vThisLevel">
<table align="center" border="1">
<tr>
<th>Name</th><th>No.</th><th>Level</th>
<xsl:apply-templates select="$vThisLevel"/>
</tr>
</table>
<br />
<br />
<xsl:call-template name="displayH">
<xsl:with-param name="pLevel" select="$pLevel + 1"/>
<xsl:with-param name="pMaxLevel" select="$pMaxLevel"/>
</xsl:call-template>
</xsl:if>
</xsl:template>

<xsl:template match="node">
<tr>
<td align="center"><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="@no"/></td>
<td><xsl:value-of select="@level"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>


when applied on the same source.xml produces the wanted output:

Name No. Level

node 1 1

node 6 1


Name No. Level

node 2 2

node 3 2

node 5 2

node 7 2

node 10 2

node 11 2


Name No. Level

node 4 3

node 8 3

node 9 3


This transformation works even in cases when levels are not consecutive
numbers (or even positive numbers) and when we do not know the starting
level.

Hope this helped.

Dimitre Novatchev.
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html


"Ruthless" <ruthless@NO_SPAM.poczta.onet.pl> wrote in message
news:bsq92m$3p5$(E-Mail Removed)...
> Hello.
>
> I've got a simple XML:
>
> <?xml version="1.0" encoding="iso-8859-2"?>
> <?xml-stylesheet type="text/xsl" href="4.xsl"?>
>
> <struct>
>
> <node level="1" no="1">
>
> <node level="2" no="2" />
> <node level="2" no="3" />
> <node level="2" no="4" />
> </node>
>
> <node level="1" no="5">
>
> <node level="2" no="6" />
> <node level="2" no="7" />
> <node level="2" no="8" />
> </node>
>
> </struct>
>
> and i want to display all the levels starting from 1 to 2
>
> I've got my xslt sth like this:
>
> <?xml version="1.0" encoding="ISO-8859-2" ?>
> <xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xslutput method="html"/>
>
> <xsl:template match="/">
>
> <html>
> <body>
>
> <table align="center" border="1">
> <tr>
> <th>Name</th><th>No.</th><th>Level</th>
> </tr>
>
> <xsl:for-each select="//node">
> <xsl:sort select="@level"/>
>
> <xsl:if test="@level='1'">
> <tr>
> <td align="center"><xsl:value-of select="name()"/></td>
> <td><xsl:value-of select="@no"/></td>
> <td><xsl:value-of select="@level"/></td>
> </tr>
> </xsl:if>
> </xsl:for-each>
>
> </table>
>
> <!-- now goes level 2-->
>
> <table align="center" border="1">
> <tr>
> <th>Name</th><th>No.</th><th>Level</th>
> </tr>
>
> <xsl:for-each select="//node">
> <xsl:sort select="@level"/>
>
> <xsl:if test="@level='2'">
> <tr>
> <td align="center"><xsl:value-of select="name()"/></td>
> <td><xsl:value-of select="@no"/></td>
> <td><xsl:value-of select="@level"/></td>
> </tr>
> </xsl:if>
> </xsl:for-each>
>
> </table>
> </body>
> </html>
>
> </xsl:template>
>
> </xsl:stylesheet>
>
> It works fine but it's useless when there would be more then 2 levels -

how
> can i loop this template to go through all the levels - each level has a

new
> table(just like above)
>
> and second thing how can i count node with e.g. attributes level="2"?
>
> I've tried sth like this:
> <xsl:template match="/">
> <xsl:variable name="ile" select="count(//node@level='2')" />
> </xsl:template>
>
> and then:
>
> <b><xsl:value-of select="$ile"/></b>
>
> but it's wrong and i've got warning msg.
>
> thanks in advance
> greetings R
>
>
> ---
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.554 / Virus Database: 346 - Release Date: 03-12-20
>
>




 
Reply With Quote
 
 
 
 
Ruthless
Guest
Posts: n/a
 
      12-30-2003
Wow man

It will take me all night to understand your example ;D

but thanks, you helped me a lot

greetings R

Użytkownik "Dimitre Novatchev" <(E-Mail Removed)> napisał w wiadomości
news:bsrena$k0j6$(E-Mail Removed)-berlin.de...
> The way to do this is the following:
>
> This transformation:
>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
>
> <xsl:template match="/">
> <html>
> <body>
> <xsl:apply-templates/>
> </body>
> </html>
> </xsl:template>
>
> <xsl:template match="*[node]">
> <table align="center" border="1">
> <tr>
> <th>Name</th><th>No.</th><th>Level</th>
> <xsl:apply-templates select="node" mode="display"/>
> </tr>
> </table>
> <br />
> <br />
> <xsl:apply-templates select="node"/>
> </xsl:template>
>
> <xsl:template match="node" mode="display">
> <tr>
> <td align="center"><xsl:value-of select="name()"/></td>
> <td><xsl:value-of select="@no"/></td>
> <td><xsl:value-of select="@level"/></td>
> </tr>
> </xsl:template>
> </xsl:stylesheet>
>
> When applied on this source.xml:
>
> <struct>
> <node level="1" no="1">
> <node level="2" no="2" />
> <node level="2" no="3">
> <node level="3" no="4"/>
> </node>
> <node level="2" no="5" />
> </node>
> <node level="1" no="6">
> <node level="2" no="7">
> <node level="3" no="8"/>
> <node level="3" no="9"/>
> </node>
> <node level="2" no="10" />
> <node level="2" no="11" />
> </node>
> </struct>
>
> Produces this output (as displayed in the browser):
>
> Name No. Level
>
> node 1 1
>
> node 6 1
>
>
>
>
> Name No. Level
>
> node 2 2
>
> node 3 2
>
> node 5 2
>
>
>
>
> Name No. Level
>
> node 4 3
>
>
>
>
> Name No. Level
>
> node 7 2
>
> node 10 2
>
> node 11 2
>
>
>
>
> Name No. Level
>
> node 8 3
>
> node 9 3
>
>
> However you want all nodes belonging to the same level to be displayed in

a
> single table.
>
> In this case this transformation:
>
>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
>
> <xsl:key name="kByLevel" match="node" use="@level"/>
>
> <xsl:variable name="vMinMaxLevel">
> <xsl:for-each
> select="//node[generate-id()
> =
> generate-id(key('kByLevel', @level)[1])
> ]">
> <xsl:sort select="@level" data-type="number"/>
>
> <xsl:if test="position() = 1 or position() = last()">
> <xsl:value-of select="@level"/>
> <xsl:if test="position() = 1">|</xsl:if>
> </xsl:if>
> </xsl:for-each>
> </xsl:variable>
>
> <xsl:template match="/">
> <xsl:call-template name="displayH">
> <xsl:with-param name="pLevel"
> select="substring-before($vMinMaxLevel, '|')"/>
> <xsl:with-param name="pMaxLevel"
> select="substring-after($vMinMaxLevel, '|')"/>
>
> </xsl:call-template>
> </xsl:template>
>
> <xsl:template name="displayH">
> <xslaram name="pLevel" select="1"/>
> <xslaram name="pMaxLevel" select="1"/>
>
> <xsl:variable name="vThisLevel"
> select="key('kByLevel', $pLevel)"/>
>
> <xsl:if test="$pLevel &lt;= $pMaxLevel
> and $vThisLevel">
> <table align="center" border="1">
> <tr>
> <th>Name</th><th>No.</th><th>Level</th>
> <xsl:apply-templates select="$vThisLevel"/>
> </tr>
> </table>
> <br />
> <br />
> <xsl:call-template name="displayH">
> <xsl:with-param name="pLevel" select="$pLevel + 1"/>
> <xsl:with-param name="pMaxLevel" select="$pMaxLevel"/>
> </xsl:call-template>
> </xsl:if>
> </xsl:template>
>
> <xsl:template match="node">
> <tr>
> <td align="center"><xsl:value-of select="name()"/></td>
> <td><xsl:value-of select="@no"/></td>
> <td><xsl:value-of select="@level"/></td>
> </tr>
> </xsl:template>
> </xsl:stylesheet>
>
>
> when applied on the same source.xml produces the wanted output:
>
> Name No. Level
>
> node 1 1
>
> node 6 1
>
>
> Name No. Level
>
> node 2 2
>
> node 3 2
>
> node 5 2
>
> node 7 2
>
> node 10 2
>
> node 11 2
>
>
> Name No. Level
>
> node 4 3
>
> node 8 3
>
> node 9 3
>
>
> This transformation works even in cases when levels are not consecutive
> numbers (or even positive numbers) and when we do not know the starting
> level.
>
> Hope this helped.
>
> Dimitre Novatchev.
> FXSL developer, XML Insider,
>
> http://fxsl.sourceforge.net/ -- the home of FXSL
> Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
>
>
> "Ruthless" <ruthless@NO_SPAM.poczta.onet.pl> wrote in message
> news:bsq92m$3p5$(E-Mail Removed)...
> > Hello.
> >
> > I've got a simple XML:
> >
> > <?xml version="1.0" encoding="iso-8859-2"?>
> > <?xml-stylesheet type="text/xsl" href="4.xsl"?>
> >
> > <struct>
> >
> > <node level="1" no="1">
> >
> > <node level="2" no="2" />
> > <node level="2" no="3" />
> > <node level="2" no="4" />
> > </node>
> >
> > <node level="1" no="5">
> >
> > <node level="2" no="6" />
> > <node level="2" no="7" />
> > <node level="2" no="8" />
> > </node>
> >
> > </struct>
> >
> > and i want to display all the levels starting from 1 to 2
> >
> > I've got my xslt sth like this:
> >
> > <?xml version="1.0" encoding="ISO-8859-2" ?>
> > <xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
> > version="1.0">
> >
> > <xslutput method="html"/>
> >
> > <xsl:template match="/">
> >
> > <html>
> > <body>
> >
> > <table align="center" border="1">
> > <tr>
> > <th>Name</th><th>No.</th><th>Level</th>
> > </tr>
> >
> > <xsl:for-each select="//node">
> > <xsl:sort select="@level"/>
> >
> > <xsl:if test="@level='1'">
> > <tr>
> > <td align="center"><xsl:value-of select="name()"/></td>
> > <td><xsl:value-of select="@no"/></td>
> > <td><xsl:value-of select="@level"/></td>
> > </tr>
> > </xsl:if>
> > </xsl:for-each>
> >
> > </table>
> >
> > <!-- now goes level 2-->
> >
> > <table align="center" border="1">
> > <tr>
> > <th>Name</th><th>No.</th><th>Level</th>
> > </tr>
> >
> > <xsl:for-each select="//node">
> > <xsl:sort select="@level"/>
> >
> > <xsl:if test="@level='2'">
> > <tr>
> > <td align="center"><xsl:value-of select="name()"/></td>
> > <td><xsl:value-of select="@no"/></td>
> > <td><xsl:value-of select="@level"/></td>
> > </tr>
> > </xsl:if>
> > </xsl:for-each>
> >
> > </table>
> > </body>
> > </html>
> >
> > </xsl:template>
> >
> > </xsl:stylesheet>
> >
> > It works fine but it's useless when there would be more then 2 levels -

> how
> > can i loop this template to go through all the levels - each level has a

> new
> > table(just like above)
> >
> > and second thing how can i count node with e.g. attributes level="2"?
> >
> > I've tried sth like this:
> > <xsl:template match="/">
> > <xsl:variable name="ile" select="count(//node@level='2')" />
> > </xsl:template>
> >
> > and then:
> >
> > <b><xsl:value-of select="$ile"/></b>
> >
> > but it's wrong and i've got warning msg.
> >
> > thanks in advance
> > greetings R
> >
> >
> > ---
> > Outgoing mail is certified Virus Free.
> > Checked by AVG anti-virus system (http://www.grisoft.com).
> > Version: 6.0.554 / Virus Database: 346 - Release Date: 03-12-20
> >
> >

>
>
>



---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.554 / Virus Database: 346 - Release Date: 03-12-20


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
looping in array vs looping in a dic giuseppe.amatulli@gmail.com Python 5 09-20-2012 11:58 PM
how to Specializations of function Templates or Overloading Function templates with Templates ? recover C++ 2 07-25-2006 02:55 AM
Monster Templates - Question about Submitting Templates Fred HTML 1 09-26-2005 01:09 AM
Templates templates templates JKop C++ 3 07-21-2004 11:44 AM
using templates in templates John Harrison C++ 8 07-31-2003 12:00 PM



Advertisments