Re: [xsl] How to display more complicated xml document by xsl (again)?

Subject: Re: [xsl] How to display more complicated xml document by xsl (again)?
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 7 Mar 2002 10:02:15 +0000
Hi Sjoy,

> This time I want to display the Keyword in order. First line(tr/td)
> will display 'group1', second line display the Keyword 3 only, and
> the last line display 'group2'.

I think that the easiest way to do this is to apply templates to all
the Keyword elements, and work out what to do with them on a case by
case basis. There are three categories that the Keywords could fall
into:

  - first in a group - output group number
  - elsewhere in a group - output nothing
  - not in a group - output keyword

You need a quick way of working out whether a particular keyword is
part of a group; you can do that with a key that indexes the Group
elements by the values of their Member elements:

<xsl:key name="groups" match="Group" use="Member" />

This way, if you do:

  key('groups', 2)

You'll get back the group that has Keyword 2 as a member.

Then you need to iterate over each Keyword:

  <xsl:for-each select="/root/Keywords/Keyword">
    ...
  </xsl:for-each>

You can locate the group that contains the keyword using the key with
the Keyword's id:

  <xsl:for-each select="/root/Keywords/Keyword">
    <xsl:variable name="group" select="key('groups', @id)" />
    ...
  </xsl:for-each>

Then you can choose what to do on the basis of $group. If there isn't
a group, then you want to output the keyword details:

  <xsl:for-each select="/root/Keywords/Keyword">
    <xsl:variable name="group" select="key('groups', @id)" />
    <xsl:choose>
      <xsl:when test="not($group)">
        <xsl:value-of select="." />
      </xsl:when>
      ...
    </xsl:choose>
  </xsl:for-each>

If the id of the Keyword you're looking at is the same as the value of
the first Member within the group, then you want to output the group
name:

  <xsl:for-each select="/root/Keywords/Keyword">
    <xsl:variable name="group" select="key('groups', @id)" />
    <xsl:choose>
      <xsl:when test="not($group)">
        <xsl:value-of select="." />
      </xsl:when>
      <xsl:when test="@id = $group/Member[1]">
        <xsl:value-of select="$group/@name" />
      </xsl:when>
    </xsl:choose>
  </xsl:for-each>

And that's it (otherwise you do nothing; you could have an empty
xsl:otherwise element, but there's no need).

Cheers,

Jeni

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


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread