Reputation: 15
I have a XML-Structure like this:
<Rootname>
<FIRST a="1" otherhattrs="whatever">
</FIRST>
<GROUPB a="b2" b="12" c="b456">
<SET NR="01">
<ENTRY type="10" otherhattr="whatever"/>
</SET>
<SET NR="02">
<ENTRY type="10" otherhattr="whatever"/>
<ENTRY type="10" otherhattr="whatever"/>
<ENTRY type="20" otherhattr="whatever"/>
</SET>
</GROUPB>
<GROUPC a="c3" b="23">
<SET NR="01">
<ENTRY type="10" otherhattr="whatever"/>
</SET>
<SET NR="02">
<ENTRY type="10" otherhattr="whatever"/>
<ENTRY type="30" otherhattr="whatever"/>
<ENTRY type="50" otherhattr="whatever"/>
</SET>
</GROUPC>
<GROUPD a="d4" b="34">
<SET NR="02">
<ENTRY type="10" otherhattr="whatever"/>
</SET>
<SET NR="03">
<ENTRY type="50" otherhattr="whatever"/>
<ENTRY type="50" otherhattr="whatever"/>
<ENTRY type="60" otherhattr="whatever"/>
</SET>
</GROUPD>
</Rootname>
My Result has to be this:
1|b2|b456|01|10|1
1|b2|b456|02|10|2
1|b2|b456|02|20|1
1|c3|23|01|10|1
1|c3|23|02|10|1
1|c3|23|02|30|1
1|c3|23|02|50|1
1|d4|34|02|10|1
1|d4|34|03|50|2
1|d4|34|03|60|1
The logic is a little bit complex, but i will describe: There are different Groups(GROUP) all belonging to the element FIRST. So first of all I need the attributes "a" of them(FIRST and GROUP) and attribute "b" of the GROUP. Second step is I need the number(NR) of the SET. Third and last step is I need the "type" of the ENTRY and the quantity of Entries (ENTRY) with the same type in the same SET.
Now there is an Exception: GROUPB is a special one, if there is an attribute "c", I don't need "b" but "c".
I thought I could solve my main-problem (the number of entries with same type in same set) by a key with {GROUP-attribute "a", SET-attribute "NR" and ENTRY-attribute "type"} but I'm frustrated, getting no keys or anything back.
My last working XSL was this, with the problem that it sorts out ENTRIES in other GROUPS and SETS:
<xsl:output method="text" encoding="ISO-8859-15" indent="no"/>
<xsl:template match="/">
<xsl:variable name="a" select="/*/FIRST/@a"/>
<xsl:if test="string($a) != ''">
<xsl:for-each select="/*/GROUPC[string(@a) != ''] | /*/GROUPB[string(@a) != '']| /*/GROUPD[string(@a) != '']">
<xsl:sort select="@a"/>
<xsl:variable name="out">
<xsl:apply-templates select=".">
<xsl:with-param name="a" select="$a"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:value-of select="$out"/>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template match="GROUPB">
<xsl:param name="a"/>
<xsl:variable name="begin">
<xsl:choose>
<xsl:when test="@c">
<xsl:value-of select="concat($a, '|', @a,'|',@c,'|')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($a, '|', @a,'|',@b,'|')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="result">
<xsl:apply-templates select="SET/ENTRY">
<xsl:with-param name="begin" select="$begin"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:value-of select="$result" />
</xsl:template>
<xsl:template match="GROUPC">
<xsl:param name="a"/>
<xsl:variable name="begin">
<xsl:value-of select="concat($a, '|', @a,'|',@b,'|')"/>
</xsl:variable>
<xsl:variable name="result">
<xsl:apply-templates select="SET/ENTRY">
<xsl:with-param name="begin" select="$begin"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:value-of select="$result" />
</xsl:template>
<xsl:template match="GROUPD">
<xsl:param name="a"/>
<xsl:variable name="begin">
<xsl:value-of select="concat($a, '|', @a,'|',@b,'|')"/>
</xsl:variable>
<xsl:variable name="result">
<xsl:apply-templates select="SET/ENTRY">
<xsl:with-param name="begin" select="$begin"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:value-of select="$result" />
</xsl:template>
<xsl:key name="art" match="ENTRY" use="@type"/>
<xsl:template match="SET">
<xsl:param name="begin"/>
<xsl:variable name="nummer">
<xsl:value-of select="@NR"/>
</xsl:variable>
<xsl:for-each select="ENTRY[generate-id() = generate-id(key('art',@type))]">
<xsl:value-of select="concat($begin, $nummer, '|', @type, '|', count(../ENTRY[@type=current()/@type]))" /><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
A last sentence, there could be GROUPS and SETS and ENTRIES without one of the wanted attributes, these ones shouldn't appear in the result.
Anybody can help me?
Upvotes: 0
Views: 140
Reputation: 116959
I got somewhat confused by your description, and I could not follow your code at all. I think you want to do something like this:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="k" match="ENTRY" use="concat(generate-id(..), '|', @type)"/>
<xsl:template match="/Rootname">
<xsl:variable name="first-a" select="FIRST/@a" />
<xsl:for-each select="*/SET/ENTRY[count(. | key('k', concat(generate-id(..), '|', @type))[1]) = 1]">
<xsl:value-of select="$first-a"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="../../@a"/>
<xsl:text>|</xsl:text>
<xsl:choose>
<xsl:when test="../../@c">
<xsl:value-of select="../../@c"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../../@b"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>|</xsl:text>
<xsl:value-of select="../@NR"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="@type"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="count(key('k', concat(generate-id(..), '|', @type)))"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2