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 <= $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