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 using Muenchian Grouping


Hi Rob,

> I have attempted to implement multi level grouping using Muenchian
> Grouping. My attempt is based on the example in the XSL List
> archive, but somewhere along the line I seem to have lost the plot.
> Could someone look at my attempt and point me in the right
> direction. The source XML XSLT and required output are shown below.

>From what I can tell, there's nothing in your requirement that
necessitates Muenchian grouping. Muenchian grouping is useful when you
don't know the possible group values, but you already know what
processarea you want to get hold of ('2') and the possible levels that
might be involved ('1' and '2'). So you don't have to do anything
complicated, just:

<xsl:variable name="processes"
  select="/assets/asset[processareas/processarea = '2']" />

<xsl:template match="assets">
  <xsl:variable name="processes"
    select="asset[processareas/processarea = '2']" />
  <xsl:if test="$processes">

    <xsl:variable name="level1"
                  select="$processes[@level = '1']" />
    <xsl:if test="$level1">
      <h1>AS Policies:</h1>
      <xsl:apply-templates select="$level1" />
    </xsl:if>

    <xsl:variable name="level2"
                  select="$processes[@level = '2']" />
    <xsl:if test="$level2">
      <h1>General:</h1>
      <xsl:apply-templates select="$level2" />
    </xsl:if>
    
  </xsl:if>
</xsl:template>

<xsl:template match="asset">
  <a href="{url}"><xsl:value-of select="assetname" /></a><br />
</xsl:template>

However, just in case you were simplifying things for posting...

>    <xsl:key name="assets-by-processarea" match="asset"
> use="processareas/processarea" />

Here, you're indexing the asset elements by their processarea
grandchildren. The trouble is that each asset element might have more
than one processarea grandchild. One of the rules when using Muenchian
grouping is that there should be a 1:1 mapping between the elements
that you're grouping and the values that you're grouping them by. So
in this case you'd be better off with:

<xsl:key name="assets-by-processarea" match="processarea" use="." />

>    <xsl:key name="assets-by-level" match="asset"
> use="concat(processareas/processarea, ' ',@level)" />

and similarly:

<xsl:key name="assets-by-level" match="processarea"
         use="concat(., ' ', ../../@level)" />

(It's actually even more of a problem with this definition because
when you get the string value of a node set (in this case to
concatenate with the level attribute), you only get the value of the
first element. As it was, you were indexing each asset by the value of
its *first* processarea concatenated with the level attribute.)
         
>    <xsl:variable name="process" select="key('assets-by-processarea',
> '2 ')" />

That looks a bit strange -- with your old key definitions, you'd get
all the asset elements whose processarea grandchild had the value
'2 '. Remember whitespace is significant here; none of the processarea
elements in your source had the value '2 ', although several had the
value '2'. Perhaps that's what you meant to use.

>    <xsl:template match="assets">
>       <xsl:for-each
> select="$process[generate-id()=generate-id(key('assets-by-level',
>       concat(processareas/processarea, ' ',@level))[1])]">
>          <xsl:if test="(@level='1')">
>             <h1>AS Policies:</h1>
>          </xsl:if>

>          <xsl:if test="(@level='2')">
>             <h1>General:</h1>
>          </xsl:if>
                
>          <a href="url"><xsl:value-of select="assetname"/></a>
>       </xsl:for-each>
>    </xsl:template>

If you just adjust this to use the new key definitions, I think it
should work:

<xsl:variable name="process"
  select="key('assets-by-processarea', '2')" />

<xsl:template match="assets">
  <xsl:for-each
    select="$process[generate-id() =
                     generate-id(key('assets-by-level',
                                     concat(., ' ', ../../@level))[1])]
              /../..">
    <xsl:sort select="@level" data-type="number" />
    <h1>
      <xsl:choose>
        <xsl:when test="@level = 1">AS Policies:</xsl:when>
        <xsl:when test="@level = 2">General:</xsl:when>
      </xsl:choose>
    </h1>
    <a href="{url}"><xsl:value-of select="assetname"/></a>
  </xsl:for-each>
</xsl:template>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 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]