Re: [xsl] Grouping problem?

Subject: Re: [xsl] Grouping problem?
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 11 Nov 2002 18:02:02 -0500
Shawn,

For many more complex grouping problems, we end up falling back on keys, which provide a neat solution to what you want here.

Declare a key to retrieve <item> elements by their @name attribute

<xsl:key name="items-by-name" match="item" use="@name"/>

Then you know if a given item is the first with its @name attribute (irrespective of where it is in the tree) if

count(. | key('items-by-name', @name)[1]) = 1

And use this same expression, if you like, in a monster predicate to select the items you are interested it:

//item[count(. | key('items-by-name', @name)[1]) = 1]

I hope that helps. Look up keys in your favorite reference for more.

Cheers,
Wendell

At 05:39 PM 11/11/2002, you wrote:
First, I'd like to thank Ken Hollman for all the help he has given me. He has saved this list much wasted bandwidth in answering my questions.

Here is a problem I am having that I think may be a grouping problem. Imagine I have nested lists of items within a document, something like this:

<section name="first">
  <nestlist name="level_1">
      <item name="apple"/>
      <item name="orange"/>
      <item name="truck"/>
      <item name="foo"/>
      <nestlist name="level_2">
        <item name="orange"/>
        <item name="bar"/>
        <item name="truck"/>
        <nestlist name="level_3">
          <item name="orange"/>
          <item name="foo"/>
          <item name="fnord"/>
          <item name="truck"/>
          <nestlist name="level_4">
            <item name="foobar"/>
            <item name="apple"/>
            <item name="bar"/>
       </nestlist>
     </nestlist>
   </nestlist>
 </nestlist>
</section>

I would like to be able to select the first instance of every item in the above with a specific name attribute, without having prior knowledge of what that name might be. For example, I would like to be able to create a select statement that would process item elements along these lines:

   - apple orange truck and foo in the level_1 nestlist
   - bar in the level_2 nestlist
   - fnord in level_3
   - foobar in level_4

I have very large lists like this, and need to perform operations on the first occurance of a unique name.

I have been attempting it with something like:

<xsl:for-each select="section">
  <xsl:variable name="sectname" select="$name"/>
  <xsl:for-each select="//nestlist/item">
    <xsl:variable name="name" select="@name"/>
      <xsl:for-each select="(/section//nestlist/item[@name=$name])[1]">
        <!--Do something here-->
      </xsl:for-each>
  +</xsl:for-each>
</xsl:for-each>

But, it seems, this is not valid. How would I go about this?


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


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



Current Thread