Subject: Re: [xsl] One nodeset, multiple branches From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 19 Dec 2001 17:44:43 +0000 |
Hi Eric, > maybe Jeni will pop in and explain the deduplication process! You rubbed my lamp... Actually, this is another example where deduplication is not particularly straight forward (the other one being deduplication across multiple documents earlier today) :( You only want to collect the right elements whose combination of module and access attributes aren't the same as other right elements that you're collecting. You can put together a node set of the right elements for the user and their groups as Wendell has shown you, so something like: <xsl:variable name="groups" select="/access/groups/group" /> <xsl:variable name="user" select="/access/users/user[username = 'evitiello']" /> <xsl:variable name="user-groups" select="$user/userGroups/group" /> <xsl:variable name="rights" select="$user/rights/right | $groups/group[@name = $user-groups/@name]/rights/right" /> One method of doing getting the unique rights is to filter the right elements you collect to only include the *first* right element that you're interested in with a particular module+access combination. Set up a key (with a top-level xsl:key element) that indexes all the right elements according to their module+access combination. You can create a 'value' for each right element, based on their module and access, by concatenating the values of the two attributes (with a separator just in case you have a module like 'newse' and a access like 'dit', which could be confused with the module 'news' and access 'edit'): <xsl:key name="rights" match="right" use="concat(@module, '+', @access)" /> You can call the key with the key() function - first argument is the name of the key, second argument is the module+access combination. For example: key('rights', 'news+add') will retrieve *all* the right elements in the document with a module attribute equal to 'news' and an access attribute equal to 'add'. You're actually only interested in the ones that you've collected together in the $rights variable, so you need to filter this set to only include those that are in the $rights node set. You can do this with set logic, as follows: key('rights', 'news+add')[count(.|$rights) = count($rights)] Then you can find the first of these in document order with a positional predicate at the end: key('rights', 'news+add')[count(.|$rights) = count($rights)][1] That gives you the first 'right' element in the user's rights whose module is 'news' and whose access is 'add'. If you're looking at a right element whose module is 'news' and whose access is 'add', you can work out whether that right element is the same as the one you've just retrieved using set logic again: count(.|key('rights', 'news+add')[count(.|$rights) = count($rights)][1]) = 1 or: generate-id() = generate-id(key('rights', 'news+add')[count(.|$rights) = count($rights)]) The value that you use as the second argument to the key() function could be based on the right element that you're looking at, so for any right element, you could work out whether it was the first in the document with that module and access using: count(.|key('rights', concat(@module, '+', @access)) [count(.|$rights) = count($rights)][1]) = 1 So you could find all the unique right elements in the list using: <xsl:variable name="unique-rights" select="$rights [count(.|key('rights', concat(@module, '+', @access)) [count(.|$rights) = count($rights)][1]) = 1]" /> Since count($rights) is going to be the same each time, it might be slightly more efficient to assign that to a variable at the start: <xsl:variable name="nrights" select="count($rights)" /> <xsl:variable name="unique-rights" select="$rights [count(.|key('rights', concat(@module, '+', @access)) [count(.|$rights) = $nrights][1]) = 1]" /> If you find that XPath monstrous, you're not alone! :) So alternatives are: - adapt the distinct template that I posted earlier today (polish my lamp again if you need help with that) - use saxon:distinct() if you're using Saxon (wipe Mike's lamp for that one) - use Dimitre's foldl generic template (buff up Dimitre's lamp for that) Cheers, Jeni (in panto mood) --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] One nodeset, multiple bra, Eric Vitiello | Thread | Re: [xsl] One nodeset, multiple bra, Wendell Piez |
[xsl] Parameter substitution, Curtis Burisch | Date | Re: [xsl] document() merge DISTINCT, Alex Schuetz |
Month |