473,467 Members | 1,559 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

looping templates

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 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output 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
Jul 20 '05 #1
2 1647
The way to do this is the following:

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="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"
xmlns:xsl="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">
<xsl:param name="pLevel" select="1"/>
<xsl:param 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:bs**********@nemesis.news.tpi.pl...
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 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output 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


Jul 20 '05 #2
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" <dn********@yahoo.com> napisał w wiadomo¶ci
news:bs***********@ID-152440.news.uni-berlin.de...
The way to do this is the following:

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="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"
xmlns:xsl="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">
<xsl:param name="pLevel" select="1"/>
<xsl:param 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:bs**********@nemesis.news.tpi.pl...
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 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output 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
Jul 20 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Tom Alsberg | last post by:
Hi there... I'm recently trying to get a bit acquainted with XML Schemas and XSL. Now, I have a few questions about XSL stylesheets and templates: * Is there a way to "enter" a child element...
22
by: E. Robert Tisdale | last post by:
According to the C++ FAQ Lite: http://www.parashift.com/ What is "genericity"? Yet another way to say, "class templates." Not to be confused with "generality" (which just means avoiding...
16
by: WittyGuy | last post by:
Hi, What is the major difference between function overloading and function templates? Thanks! http://www.gotw.ca/resources/clcm.htm for info about ]
5
by: k.a.bouton | last post by:
I am trying to transform my XML to produce just a tree of the unique nodes and subnodes and am having no luck. this is the sample xml <MyRoot> <contact> <name>Jane Doe</name>...
2
by: Claire Reed | last post by:
Dear All, I am repeatedly encountering a problem whilst looping through XML Nodes and I am unsure as to what is going on and how I can get around it. I load the following XML document into an...
4
by: Eric | last post by:
Hello, I've found syntax documentation on the document XSLT function, but I haven't found a good resource yet on how to properly use it. As stripped down example, I have XML files that are...
25
by: Ted | last post by:
I'm putting the posts that follow here (hopefully they will follow here!) because they were rejected in comp.lang.c++.moderated. It behooves anyone reading them to first read the the thread of the...
1
by: tom | last post by:
Hi all The next thing I'm trying to do here at www.guitarmidi.co.uk is show how many results a query returns above a table displaying those results. Doing this willl eventually lead to showing...
28
by: NewToCPP | last post by:
Hi, I am just trying to find out if there is any strong reason for not using Templates. When we use Templates it is going to replicate the code for different data types, thus increasing the...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.