This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: Multi-level grouping problem. MSXML bug, maybe?
- From: TSchutzerWeissmann at uk dot imshealth dot com
- To: xsl-list at lists dot mulberrytech dot com
- Date: Thu, 9 May 2002 10:03:06 +0100
- Subject: RE: [xsl] Multi-level grouping problem. MSXML bug, maybe?
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hello Mark,
The problem is here:
<xsl:for-each select="/recordset/row
[TYPE/@value = $type and SUB_TYPE/@value = $subtype]
/D_CODE[count(. | key('d-by-type-subtype',
concat($type, '|'$subtype)[1]) = 1]">
<!--
<xsl:for-each select="/recordset/row[TYPE/@value = $type and
SUB_TYPE/@value = $subtype]/D_CODE[not(preceding::D_CODE/@value = @value)]">
-->
<DG>
<xsl:attribute name="Code"><xsl:value-of
select="@value"/></xsl:attribute>
</DG>
<!-- </xsl:for-each> -->
</xsl:for-each>
it's a bit OTT.
You've abandoned the grouping on TYPE and SUB-TYPE that is the current
context, re-searched on TYPE & SUB-TYPE, then chosen the first D_CODE child
of the grouped row elements that is a member of a grouping of D_CODEs of
TYPE and SUB-TYPE.
Apart from being overkill x 3, this Xpath will only return one element.
Hence the commented-out for-each
You've already grouped the rows by TYPE and SUB-TYPE. So if your D_CODE
elements are siblings of TYPE and SUB_TYPE, you won't need to do it again:
the context you're in will give you what you need.
So couldn't you just have
<xsl:for-each select="DG_CODE">
<xsl:sort select="@value"/>
<DG>
<xsl:attribute name="Code"><xsl:value-of
select="@value"/></xsl:attribute>
</DG>
</xsl:for-each>
?
Regards,
Tom Weissmann
-----Original Message-----
From: mpfingstler@triseptsolutions.com
[mailto:mpfingstler@triseptsolutions.com]
Sent: 09 May 2002 05:04
To: XSL-List@lists.mulberrytech.com
Subject: [xsl] Multi-level grouping problem. MSXML bug, maybe?
Hi all,
I've been stuck on this for the last several hours and I can't figure out
why this isn't producing what I think it should.
Given this xml:
<?xml version="1.0"?>
<recordset>
<row>
<CODE value="000001"/>
<CATEGORY_CODE value="A"/>
<SUB_CATEGORY_CODE value="E"/>
<ID value="ID01"/>
<TYPE value="F"/>
<SUB_TYPE value="S"/>
<D_CODE value="V"/>
<D_DESC value=""/>
</row>
<row>
<CODE value="000001"/>
<CATEGORY_CODE value="A"/>
<SUB_CATEGORY_CODE value="L"/>
<ID value="ID02"/>
<TYPE value="F"/>
<SUB_TYPE value="S"/>
<D_CODE value="V"/>
<D_DESC value=""/>
</row>
<row>
<CODE value="000001"/>
<CATEGORY_CODE value="B"/>
<SUB_CATEGORY_CODE value="E"/>
<ID value="ID03"/>
<TYPE value="F"/>
<SUB_TYPE value="T"/>
<D_CODE value="V"/>
<D_DESC value=""/>
</row>
<row>
<CODE value="000002"/>
<CATEGORY_CODE value="S"/>
<SUB_CATEGORY_CODE value="L"/>
<ID value="ID04"/>
<TYPE value="F"/>
<SUB_TYPE value="S"/>
<D_CODE value="F"/>
<D_DESC value=""/>
</row>
</recordset>
I want the output to look like:
<?xml version="1.0" encoding="iso-8859-1"?>
<CS>
<Co Type="F" SubType="S">
<DG Code="V" />
<DG Code="F" />
</Co>
<Co Type="F" SubType="T">
<DG Code="V" />
</Co>
</CS>
That is, I'm grouping by TYPE, SUB_TYPE, and D_CODE.
Here is the stylesheet:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:user="http://mycompany.com/mynamespace"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="user msxsl"
version="1.0">
<xsl:output method="xml" indent="yes" encoding="iso-8859-1"/>
<xsl:strip-space elements="*"/>
<xsl:key name="row-by-type-subtype" match="row" use="concat(TYPE/@value,
'|', SUB_TYPE/@value)"/>
<xsl:key name="d-by-type-subtype" match="D_CODE"
use="concat(../TYPE/@value, '|', ../SUB_TYPE/@value)"/>
<xsl:template match="/">
<CS>
<xsl:for-each select="/recordset/row[count(. |
key('row-by-type-subtype', concat(TYPE/@value, '|', SUB_TYPE/@value))[1]) =
1]">
<xsl:variable name="type" select="TYPE/@value"/>
<xsl:variable name="subtype" select="SUB_TYPE/@value"/>
<Co>
<xsl:attribute name="Type"><xsl:value-of
select="$type"/></xsl:attribute>
<xsl:attribute name="SubType"><xsl:value-of
select="$subtype"/></xsl:attribute>
<xsl:for-each select="/recordset/row[TYPE/@value = $type and
SUB_TYPE/@value = $subtype]/D_CODE[count(. | key('d-by-type-subtype',
concat($type, '|', $subtype))[1]) = 1]">
<!--
<xsl:for-each select="/recordset/row[TYPE/@value = $type and
SUB_TYPE/@value = $subtype]/D_CODE[not(preceding::D_CODE/@value = @value)]">
-->
<DG>
<xsl:attribute name="Code"><xsl:value-of
select="@value"/></xsl:attribute>
</DG>
</xsl:for-each>
</Co>
</xsl:for-each>
</CS>
</xsl:template>
</xsl:stylesheet>
Instead it looks like:
<?xml version="1.0" encoding="iso-8859-1"?>
<CS>
<Co Type="F" SubType="S">
<DG Code="V" />
</Co>
<Co Type="F" SubType="T">
<DG Code="V" />
</Co>
</CS>
If I use the commented-out for-each, I get this instead:
<?xml version="1.0" encoding="iso-8859-1"?>
<CS>
<Co Type="F" SubType="S">
<DG Code="V" />
<DG Code="F" />
</Co>
<Co Type="F" SubType="T"></Co>
</CS>
I'm using MSXML3. I tried MSXML4 also, but I get the same result. So why am
I not getting the output I expected? Also, is there a better way to do a
multiple "group-by"?
Thanks for your help.
Mark
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list