Usually my input XML files are much bigger but this one is a good
example.
The <action> elements all have the value "delete" but this is not a
problem.
There are two groups (I'm only interested in the children of <data>
that have <action> elements): breakdown and breakdownlanguage.
I repeat that I need, for each of both groups, to build an HTML table.
To set the headers of those tables, I must get all possible children of
a category (the children differ from one member of a group to another,
but a member has only one child of a certain kind). Then the tables are
filled with the textnode values of those children (a field can be blank
if there is no child of a certain category).
(But then, in a way, I must pay attention to the order of the headers).
If someone could show me how nested grouping works, using the Muenchian
method...
The solution is straightforward:
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:key name="kGrps" match="data/*[action]"
use="name()"/>
<xsl:key name="ktabRows" match="data/*[action]/*"
use="concat(name(..), '|', name())"/>
<xsl:template match="/">
<xsl:for-each
select="*/data/*[generate-id()
=
generate-id(key('kGrps', name())[1])
]">
<xsl:value-of select="name()"/>
<br />
<table border="1">
<tr>
<xsl:for-each
select="/*/data/*[action]/*
[generate-id()
=
generate-id(key('ktabRows',
concat(name(current()),
'|',
name()
)
)[1]
)
]">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</tr>
<xsl:for-each select="key('kGrps', name())">
<xsl:variable name="vRow" select="."/>
<tr>
<xsl:for-each
select="/*/data/*[action]/*
[generate-id()
=
generate-id(key('ktabRows',
concat(name(current()),
'|',
name()
)
)[1]
)
]">
<td>
<xsl:choose>
<xsl:when test="$vRow/*[name() = name(current())]">
<xsl:value-of
select="$vRow/*[name() = name(current())]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="' '"/>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
<br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
when applied on your xml source:
<dump>
<identification>
<version> 1.0</version>
<date> 17/04/2003</date>
</identification>
<data>
<project eiac="PISCINE">
<eiac> PISCINE</eiac>
<lotnum> Lot 1</lotnum>
<contractnum> 0011</contractnum>
<lcnstructure> 11222333</lcnstructure>
<projectpricecoef> 0.000</projectpricecoef>
<projectpricecur> EUR</projectpricecur>
<totalsystems> 1</totalsystems>
<xafree1> REF LSA</xafree1>
<xafree2> Rev</xafree2>
<xafree10> ED1</xafree10>
</project>
<breakdown eiac="PISCINE" lcn="P1AA00XX" alc="00">
<action> delete</action>
<eiac> PISCINE</eiac>
<lcn> P1AA00XX</lcn>
<alc> 00</alc>
<lcntype> P</lcntype>
<uoc1> PS1</uoc1>
<xbfree1> ED1</xbfree1>
<xbfree2> E</xbfree2>
</breakdown>
<breakdown eiac="PISCINE" lcn="P1AA00XX001" alc="00">
<action> delete</action>
<eiac> PISCINE</eiac>
<lcn> P1AA00XX001</lcn>
<alc> 00</alc>
<lcntype> P</lcntype>
<breakramind> Y</breakramind>
<uoc1> PS1</uoc1>
<uoc2> PS2</uoc2>
<xbfree1> ED1</xbfree1>
<xbfree2> F</xbfree2>
</breakdown>
<breakdown eiac="PISCINE" lcn="P1AA01AB" alc="01">
<action> delete</action>
<eiac> PISCINE</eiac>
<lcn> P1AA01AB</lcn>
<alc> 01</alc>
<lcntype> P</lcntype>
<breakramind> Y</breakramind>
<uoc1> PS2</uoc1>
<xbfree1> ED1</xbfree1>
<xbfree2> E</xbfree2>
</breakdown>
<breakdownlanguage eiac="PISCINE" lcn="P1AA00" alc="01" language="FR">
<eiac> PISCINE</eiac>
<lcn> P1AA00</lcn>
<alc> 01</alc>
<lcntypexb1> P</lcntypexb1>
<language> FR</language>
<lcnnom> S_SYST FILTRATION</lcnnom>
<lcnnomfull> S_SYST FILTRATION</lcnnomfull>
</breakdownlanguage>
<breakdownlanguage eiac="PISCINE" lcn="P1AA00XX003" alc="01"
language="FR">
<action> delete</action>
<eiac> PISCINE</eiac>
<lcn> P1AA00XX003</lcn>
<alc> 01</alc>
<lcntypexb1> P</lcntypexb1>
<language> FR</language>
</breakdownlanguage>
<breakdownlanguage eiac="PISCINE" lcn="P1AA00XX" alc="00"
language="EN">
<action> delete</action>
<eiac> PISCINE</eiac>
<lcn> P1AA00XX</lcn>
<alc> 00</alc>
<lcntypexb1> P</lcntypexb1>
<language> EN</language>
<lcnnom> ALIMENTATION EAUX</lcnnom>
<lcnnomfull> ALIMENTATION EAUX</lcnnomfull>
</breakdownlanguage>
</data>
</dump>
produces the wanted result:
breakdown<br/>
<table border="1">
<tr>
<td>action</td>
<td>eiac</td>
<td>lcn</td>
<td>alc</td>
<td>lcntype</td>
<td>uoc1</td>
<td>xbfree1</td>
<td>xbfree2</td>
<td>breakramind</td>
<td>uoc2</td>
</tr>
<tr>
<td> delete</td>
<td> PISCINE</td>
<td> P1AA00XX</td>
<td> 00</td>
<td> P</td>
<td> PS1</td>
<td> ED1</td>
<td> E</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> delete</td>
<td> PISCINE</td>
<td> P1AA00XX001</td>
<td> 00</td>
<td> P</td>
<td> PS1</td>
<td> ED1</td>
<td> F</td>
<td> Y</td>
<td> PS2</td>
</tr>
<tr>
<td> delete</td>
<td> PISCINE</td>
<td> P1AA01AB</td>
<td> 01</td>
<td> P</td>
<td> PS2</td>
<td> ED1</td>
<td> E</td>
<td> Y</td>
<td> </td>
</tr>
</table>
<br/>breakdownlanguage<br/>
<table border="1">
<tr>
<td>action</td>
<td>eiac</td>
<td>lcn</td>
<td>alc</td>
<td>lcntypexb1</td>
<td>language</td>
<td>lcnnom</td>
<td>lcnnomfull</td>
</tr>
<tr>
<td> delete</td>
<td> PISCINE</td>
<td> P1AA00XX003</td>
<td> 01</td>
<td> P</td>
<td> FR</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> delete</td>
<td> PISCINE</td>
<td> P1AA00XX</td>
<td> 00</td>
<td> P</td>
<td> EN</td>
<td> ALIMENTATION EAUX</td>
<td> ALIMENTATION EAUX</td>
</tr>
</table>
<br/>
Hope this helped.
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list