Subject: Re: [xsl] First Element in Sorted List|
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Fri, 18 Nov 2005 20:40:52 +1100
On 6/2/05, Michael Kay <mike@xxxxxxxxxxxx> wrote: > > > > My process needs to take action on the first element in a list of > > elements where the logic to determine first is the lowest > > numeric value > > of the sortorder attribute. I don't believe there is a > > one-line way to > > do this - I believe the entire list must be sorted, and then the > > position of each element after sort compared to determine if > > it is first. > > Yes. Even in XSLT 2.0 this may be the best approach. 2.0 offers min/max > functions, but they give you the highest/lowest value, not the node having > that value. > > Writing a recursive template/function might give you better performance than > sorting (linear rather than n*log(n)). > > There is a one-line solution: $x[not($x/@sortorder < @sortorder)] but it's > quite likely to have poor (quadratic) performance. > > You could consider using EXSLT math:highest() or math:lowest(). > > Or I'm sure there's something in Dimitre's box of tricks called FXSL. > > Michael Kay > http://www.saxonica.com/ The following FXSL one-liner does the job: <xsl:sequence select= "2*f:xsltSort(/*/*/@sortorder/xs:integer(.), f:add(0))"/> In this case, the "do-something" operation on the minimum item of the sequence is double-it. When evaluated against the following source xml: <t> <x sortorder="3"/> <x sortorder="2"/> <x sortorder="5"/> <x sortorder="8"/> <x sortorder="7"/> <x sortorder="9"/> <x sortorder="6"/> <x sortorder="4"/> <x sortorder="1"/> <x sortorder="2"/> </t> The correct result: 2 is produced. The f:xsltSort() function is simply a wrapper around the xsl:perform-sort instruction. It accepts a list of functions, which are composed to produce the effect of multiple sort keys. Here's the code of the function: <xsl:function name="f:xsltSort" as="item()*"> <xsl:param name="pSeq" as="item()*"/> <xsl:param name="pCriteria" as="node()*"/> <xsl:perform-sort select="$pSeq"> <xsl:sort select="f:compose-flist($pCriteria, .)"/> </xsl:perform-sort> </xsl:function> Certainly, in a future refinement I should also either process an explicitly passed type-argument (e.g. number or text) or find a way to efficiently determine the common most non-generic type of all items in a sequence. Any ideas? -- Cheers, Dimitre Novatchev --------------------------------------- To avoid situations in which you might make mistakes may be the biggest mistake of all.