This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: Multi-level grouping problem. MSXML bug, maybe?


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]