At 2011-12-14 22:37 +0200, Adrian Herscu wrote:
I am using XSL 1.0.
In the classroom I cover three ways to approach grouping with XSLT
1. In your case where you have multiple levels of groups, I usually
use the variable method (this method is also helpful across multiple files):
t:\ftemp>type adrian.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="test">
<test>
<xsl:variable name="suite" select="suite"/>
<xsl:for-each select="$suite">
<xsl:if test="generate-id(.)=
generate-id($suite[@name=current()/@name])">
<suite name="{@name}">
<xsl:variable name="case"
select="$suite[@name=current()/@name]/case"/>
<xsl:for-each select="$case">
<xsl:if test="generate-id(.)=
generate-id($case[@name=current()/@name])">
<case name="{@name}">
<xsl:copy-of select="$case[@name=current()/@name]/procedure"/>
</case>
</xsl:if>
</xsl:for-each>
</suite>
</xsl:if>
</xsl:for-each>
</test>
</xsl:template>
</xsl:stylesheet>
t:\ftemp>xslt adrian.xml adrian.xsl
<?xml version="1.0" encoding="utf-8"?>
<test>
<suite name="A">
<case name="A">
<procedure name="A"/>
<procedure name="B"/>
</case>
<case name="B">
<procedure name="A"/>
</case>
</suite>
</test>
t:\ftemp>type adrian.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="test">
<test>
<xsl:variable name="suite" select="suite"/>
<xsl:for-each select="$suite">
<xsl:if test="generate-id(.)=
generate-id($suite[@name=current()/@name])">
<suite name="{@name}">
<xsl:variable name="case"
select="$suite[@name=current()/@name]/case"/>
<xsl:for-each select="$case">
<xsl:if test="generate-id(.)=
generate-id($case[@name=current()/@name])">
<case name="{@name}">
<xsl:copy-of select="$case[@name=current()/@name]/procedure"/>
</case>
</xsl:if>
</xsl:for-each>
</suite>
</xsl:if>
</xsl:for-each>
</test>
</xsl:template>
</xsl:stylesheet>
t:\ftemp>
I see you've tried to use the Muenchian method, which can be done,
and you are approaching it correctly, but I have some comments:
My last attempt to solve it this evening was:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="suites" match="//suite" use="@name" />
<xsl:key name="cases" match="//case" use="concat(../@name,
'.', @name)" />
The "//" is not needed in either of the above.
Be careful of the "." delimiter, which may work fine for your data
... I typically use a character unlikely to be found in the XML content
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="test">
<test>
<xsl:for-each select="//suite">
<xsl:if test="generate-id() =
generate-id(key('suites',@name)[1])">
<xsl:apply-templates select="." />
</xsl:if>
</xsl:for-each>
The above can be more compact by using a predicate and simply pushing
rather than doing both a pull and a push.
</test>
</xsl:template>
<xsl:template match="suite">
<suite name="{@name}">
<xsl:for-each select="//case">
<xsl:if test="generate-id() =
generate-id(key('cases',concat(../@name, '.', @name))[1])">
<xsl:apply-templates select="." />
</xsl:if>
</xsl:for-each>
</suite>
</xsl:template>
<xsl:template match="case">
<case name="{@name}" />
</xsl:template>
</xsl:stylesheet>
which rendered duplicate cases :(
<?xml version="1.0" encoding="UTF-8"?>
<test>
<suite name="A">
<case name="A" />
<case name="B" />
<case name="B" />
</suite>
<suite name="C">
<case name="A" />
<case name="B" />
<case name="B" />
</suite>
</test>
Wait ... that output is for data that isn't the same as the data you
had in your original post.
What is your input data so that I can mimic your incorrect results
and then repair what you have?
. . . . . . . . . . . Ken
--
Contact us for world-wide XML consulting and instructor-led training
Free 5-hour video lecture: XSLT/XPath 1.0 & 2.0 http://ude.my/uoui9h
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
G. Ken Holman mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--