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

Re: Re: sorting a variable that contains a nodeset

Subject: Re: Re: sorting a variable that contains a nodeset
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 10 Jan 2002 19:00:50 +0000
xsl for each select contains
Hi Rafael,

>>My intuition tells me that you might be wanting to do this because
>>you want to create groups of ARTICULO elements. If that's the case,
>>then there are different (and more portable) ways to go about it, so
>>let us know if that's what you're trying to do.
>
> Hi Jeni! You said it! I want to group articles depending on its
> category and subcategory to show them grouped in a table. I´d thank
> you your ideas!

OK. I'll show you the Muenchian grouping method. You might want to
look at http://www.jenitennison.com/xslt/grouping for more examples
and explanation.

Assuming that you want to group first by NOMBRE_FAMILIA and then by
NOMBRE_SUBFAMILIA, you need to construct two keys. The first indexes
all the ARTICULO elements by their NOMBRE_FAMILIA child element:

<xsl:key name="familia" match="ARTICULO" use="NOMBRE_FAMILIA" />

and the second indexes all the ARTICULO elements by their
NOMBRE_FAMILIA *and* NOMBRE_SUBFAMILIA child elements by concatenating
these values together:

<xsl:key name="familia-and-subfamilia" match="ARTICULO"
         use="concat(NOMBRE_FAMILIA, '+', NOMBRE_SUBFAMILIA)" />

You can then use the key() function to quickly access the ARTICULO
elements. For example:

  key('familia', 'alimentacion')

would return all the ARTICULO elements whose NOMBRE_FAMILIA had a
value of 'alimentacion'.

Likewise:

  key('familia-and-subfamilia', 'alimentacion+carnes')

would return all the ARTICULO elements whose NOMBRE_FAMILIA was
'alimentacion' and whose NOMBRE_SUBFAMILIA was 'carnes'.

So given that the context node is an ARTICULO element, you can find
all the other ARTICULO elements with the same NOMBRE_FAMILIA with:

  key('familia', NOMBRE_FAMILIA)

You can then test whether the ARTICULO element that you're looking at
is the same as the first of the ARTICULO elements returned by the key.
If it is, then it's the first ARTICULO in the document with that value
for NOMBRE_FAMILIA. You can test whether they're the same ARTICULO in
two ways:

  generate-id() = generate-id(key('familia', NOMBRE_FAMILIA)[1])

or:

  count(.|key('familia', NOMBRE_FAMILIA)[1]) = 1

You can collect all the ARTICULO elements for which this is true (i.e.
the first in the document with that NOMBRE_FAMILIA) with the
following:

  ARTICULO[count(.|key('familia', NOMBRE_FAMILIA)[1]) = 1]

Thus, you can iterate over each of the ARTICULO elements with a unique
NOMBRE_FAMILIA, in NOMBRE_FAMILIA order with:

  <xsl:for-each
    select="ARTICULO[count(.|key('familia', NOMBRE_FAMILIA)[1]) = 1]">
    <xsl:sort select="NOMBRE_FAMILIA" />
    Familia: <xsl:value-of select="NOMBRE_FAMILIA" />
    ...
  </xsl:for-each>

You can do a similar kind of thing for the second-level sort:

  <xsl:for-each
    select="ARTICULO[count(.|key('familia', NOMBRE_FAMILIA)[1]) = 1]">
    <xsl:sort select="NOMBRE_FAMILIA" />
    
    Nombre Familia: <xsl:value-of select="NOMBRE_FAMILIA" />

    <xsl:for-each
      select="key('familia', NOMBRE_FAMILIA)
                [count(.|key('familia-and-subfamilia',
                             concat(NOMBRE_FAMILIA, '+',
                                    NOMBRE_SUBFAMILIA)[1]) = 1]">
      <xsl:sort select="NOMBRE_SUBFAMILIA" />

      Nombre Subfamilia: <xsl:value-of select="NOMBRE_SUBFAMILIA" />
      ...
    </xsl:for-each>
  </xsl:for-each>

And then iterate over all the ARTICULO elements in that subgroup using
the familia-and-subfamilia key again to produce whatever details you
like.

  <xsl:for-each
    select="ARTICULO[count(.|key('familia', NOMBRE_FAMILIA)[1]) = 1]">
    <xsl:sort select="NOMBRE_FAMILIA" />
    
    Nombre Familia: <xsl:value-of select="NOMBRE_FAMILIA" />

    <xsl:for-each
      select="key('familia', NOMBRE_FAMILIA)
                [count(.|key('familia-and-subfamilia',
                             concat(NOMBRE_FAMILIA, '+',
                                    NOMBRE_SUBFAMILIA))[1]) = 1]">
      <xsl:sort select="NOMBRE_SUBFAMILIA" />

      Nombre Subfamilia: <xsl:value-of select="NOMBRE_SUBFAMILIA" />

      <xsl:for-each
        select="key('familia-and-subfamilia',
                    concat(NOMBRE_FAMILIA, '+', NOMBRE_SUBFAMILIA))">
        <xsl:sort select="DESCRIPCION_CORTA"/>
        
        <xsl:value-of select="DESCRIPCION_CORTA" />

      </xsl:for-each>
    </xsl:for-each>
  </xsl:for-each>

Cheers,

Jeni

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


 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.