Re: Can someone explain this snippet? Muenchian sorting.

Discussion in 'XML' started by Marrow, Jul 4, 2003.

  1. Marrow

    Marrow Guest

    Hi Jim,

    > Anyway, the "count(. | key('contacts-by-surname', surname)[1]) = 1"

    bit
    > is throwing me for a loop, I can't figure out what's going on there. Are
    > you trying to OR the current context node with the first value of the node
    > set returned from the key() function? What happens when you do that?


    It is usually best to keep in mind that the | operator is union (rather than
    OR).

    When, in XPath, you do a union of two node-sets the resulting node-set will
    only ever contain each individual node once (i.e. a node-set can never
    contain a particular node twice or more).

    There are some common patterns of XPath/XSLT that you get used to seeing -
    two in particular are...
    count(. | something[1]) = 1
    and...
    generate-id(.) = generate-id(something[1])
    Both of these are saying...
    is the current context node (.) the same actual node as the something[1]
    node

    > <xsl:for-each select="contact[count(. | key('contacts-by-surname',
    > surname)[1]) = 1]">


    For every <contact> node check if this <contact> is the same as the first
    <contact> node returned by the key 'contacts-by-surname' for this value of
    the <contact>'s child <surname> element.

    See also: http://www.topxml.com/code/default.asp?p=3&id=v20010304154028

    > "contact[generate-id() = generate-id(key('contacts-by-surname',
    > surname)[1])]"


    Is doing much the same - but comparing the two generated ids to see if this
    <contact> is the first one with this value of <surname>.

    A couple of tips:-
    1) the generate-id() variation of the Muenchian Technique is usually
    (always?) faster;
    2) when using the generate-id() variation the index predicate (i.e. the
    '[1]' part) is completely superfluous because generate-id() only ever
    returns the generated id of the first node in the passed node-set. In most
    transformation engines adding the '[1]' index predicate will have a slight
    (but cumulative) performance impact - because you are doing something that
    the generate-id() function will do anyway.

    Cheers
    Marrow
    http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
    http://www.topxml.com/Xselerator

    "Jim Bancroft" <> wrote in message
    news:Q0YMa.35$...
    > I've been reading up on the "Muenchian" sorting method on
    > www.jenitennison.com, and saw this use of the count() function:
    >
    > <xsl:for-each select="contact[count(. | key('contacts-by-surname',
    > surname)[1]) = 1]">
    >
    > What's happening is the code is trying to select the first node in a
    > set, given a particular key. At least that's what I think.
    >
    > Anyway, the "count(. | key('contacts-by-surname', surname)[1]) = 1"

    bit
    > is throwing me for a loop, I can't figure out what's going on there. Are
    > you trying to OR the current context node with the first value of the node
    > set returned from the key() function? What happens when you do that?
    >
    > Another way of doing the same thing seems to be as follows, (and

    thanks
    > to Marrow for helping me with a similar problem yesterday):
    >
    > "contact[generate-id() = generate-id(key('contacts-by-surname',
    > surname)[1])]"
    >
    > I understand this a little more, it looks like you want the node whose
    > id (conveniently created via "generate-id()") matches the first one

    returned
    > by the key. Please correct me if I misunderstood that or any other

    portion
    > of the code I posted. Thanks!
    >
    > -Jim
    Marrow, Jul 4, 2003
    #1
    1. Advertising

  2. Marrow

    Jim Bancroft Guest

    Thanks again for the explanation, Marrow.

    I hate to ask for another favor, you've been really helpful, but could I ask
    you a question about this? It's from a post you showed me on July 2nd:


    <!---------------------------------------------------------------->
    <xsl:key name="kDistinctPartName" match="part" use="name"/>
    <!--more stuff goes here, snip-->

    <!-- copy only the highest version of this distinct part name -->
    <xsl:copy-of select="key('kDistinctPartName',@name)[not(@name
    &lt;key('kDistinctPartName',@name))][1]"/>
    <!------------------------------------------------------------------>

    The "[not(@name &lt;key('kDistinctPartName',@name))]" predicate is a little
    strange to my ear. Seems to me you're looking for a node whose @name
    attribute is *not* less than the one returned by the key. My question is:
    are you only comparing the first element of the key, or does the &lt;
    somehow compare the @name with *all* elements of the key?

    Sorry for the trouble!


    -Jim
    Jim Bancroft, Jul 7, 2003
    #2
    1. Advertising

  3. Marrow

    Marrow Guest

    Hi Jim,

    > Sorry for the trouble!


    No trouble at all. :)

    > The "[not(@name &lt;key('kDistinctPartName',@name))]" predicate is a

    little
    > strange to my ear. Seems to me you're looking for a node whose @name
    > attribute is *not* less than the one returned by the key. My question is:
    > are you only comparing the first element of the key, or does the &lt;
    > somehow compare the @name with *all* elements of the key?


    The latter - it is comparing @name with all nodes returned by the key.
    Remember that the key() function just returns a node-set... so it is the
    usual process of comparing node-sets.

    Cheers
    Marrow


    "Jim Bancroft" <> wrote in message
    news:wEgOa.22$...
    > Thanks again for the explanation, Marrow.
    >
    > I hate to ask for another favor, you've been really helpful, but could I

    ask
    > you a question about this? It's from a post you showed me on July 2nd:
    >
    >
    > <!---------------------------------------------------------------->
    > <xsl:key name="kDistinctPartName" match="part" use="name"/>
    > <!--more stuff goes here, snip-->
    >
    > <!-- copy only the highest version of this distinct part name -->
    > <xsl:copy-of select="key('kDistinctPartName',@name)[not(@name
    > &lt;key('kDistinctPartName',@name))][1]"/>
    > <!------------------------------------------------------------------>
    >
    > The "[not(@name &lt;key('kDistinctPartName',@name))]" predicate is a

    little
    > strange to my ear. Seems to me you're looking for a node whose @name
    > attribute is *not* less than the one returned by the key. My question is:
    > are you only comparing the first element of the key, or does the &lt;
    > somehow compare the @name with *all* elements of the key?
    >
    > Sorry for the trouble!
    >
    >
    > -Jim
    >
    >
    >
    >
    >
    >
    Marrow, Jul 7, 2003
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Colin Mackenzie
    Replies:
    0
    Views:
    1,109
    Colin Mackenzie
    Jul 3, 2003
  2. Replies:
    1
    Views:
    636
    Joris Gillis
    Jun 6, 2006
  3. Replies:
    1
    Views:
    642
  4. Ajinkya

    explain the code snippet

    Ajinkya, May 11, 2007, in forum: C Programming
    Replies:
    8
    Views:
    443
    Chris Dollin
    May 14, 2007
  5. Replies:
    1
    Views:
    293
    Victor Bazarov
    Oct 22, 2007
Loading...

Share This Page