[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: different first element in a list

Subject: Re: different first element in a list
From: Mike Brown <mike@xxxxxxxx>
Date: Sat, 22 Feb 2003 15:15:39 -0700 (MST)
marc tomasi
Lorenzo De Tomasi wrote:
> I have an Xml list, for esample this list of skills:
> 
> <skills>
>     <skill mark="excellent" name="excellentskill">
>     <skill mark="excellent" name="excellent skill">
>     <skill mark="good" name="goodskill">
>     <skill mark="good" name="goodskill">
>     <skill mark="basic" name="basicskill">
>     <skill mark="basic" name="basicskill">
>     <skill mark="excellent" name="excellentskill">
>     <skill mark="good" name="goodskill">
>     <skill mark="basic" name="basicskill">
> </skills>
> 
> and I want to list in groups based on 'mark' attribute:
> [...]
> What I want to obtain is an xhtml list like this
> 
> excellent skills:   excellentskill
>                     excellentskill
>                     excellentskill
> good skills:        goodskill
>                     goodskill
>                     goodskill
> basic skills:       basicskill
>                     basicskill
>                     basicskill
> 
> using <div>s or <table>s

Grouping problems are a FAQ. The most efficient solution is explained at
http://www.jenitennison.com/xslt/grouping/muenchian.html, and in your
case would look something like this:

  <xsl:key name="skills-by-mark" match="skill" use="@mark"/>
  <xsl:template match="skills">
    <table>
      <!-- process a set consisting of the first skill element for each mark -->
      <xsl:for-each select="skill[count(.|key('skills-by-mark',@mark)[1])=1]">
        <tr>
          <td><b><xsl:value-of select="concat(@mark,' skills:')"/></b></td>
          <td>
            <!-- process all skill elements having the current skill's mark -->
            <xsl:for-each select="key('skills-by-mark',@mark)">
              <xsl:value-of select="@name"/>                
              <xsl:if test="position()!=last()"><br/></xsl:if>
            </xsl:for-each>
          </td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>

There is an easier to understand, but less efficient, way that doesn't use
keys, but does the same thing, first identifying the set of skill elements
that are the first ones with that mark, and then for each of those,
finding the rest with that mark.

<xsl:for-each select="skill[not(@mark=preceding-sibling::skill/@mark)]">
  ...
  <xsl:for-each select=".|following-sibling::skill[@mark=current()/@mark]">
    ...


Mike

-- 
  Mike J. Brown   |  http://skew.org/~mike/resume/
  Denver, CO, USA |  http://skew.org/xml/

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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.