Subject: RE: [xsl] sorting a subset of elements From: "Dion Houston" <dionh@xxxxxxxxxxxxx> Date: Thu, 22 Aug 2002 00:25:53 -0700 |
With XSLT 1.0 and nearly every XSLT processor I'm aware of you can sort, filter, and sort again, however the way to do this is processor dependent. With MSXML and System.Xml for example: (note this is pseudo-XSL) <xsl:stylesheet ... xmlns:msxsl="urn:schemas-microsoft-com:xslt"> <xsl:param name="NumberToReturn" select="90"/> <xsl:template match="/"> <xsl:variable name="SortedByPrice.tf"> <xsl:apply-templates select="/Path/To/My/Interesting/Node"> <xsl:sort select="@price" data-type="number"/> </xsl:apply-templates> </xsl:variable> <xsl:variable name="SortedByPrice" select="msxsl:node-set($SortedByPrice.tf)"/> <xsl:for-each select="$SortedByPrice/*[position() < $NumberToReturn + 1]"> <xsl:sort select="@name"/> <!-- output it --> <xsl:copy-of select="."/> </xsl:for-each> </xsl:template> <xsl:template match="Node"> <xsl:copy> <xsl:copy-of select="@*"/> </xsl:copy> </xsl:template> </xsl:stylesheet> HTH! Dion -----Original Message----- From: Jarno.Elovirta@xxxxxxxxx [mailto:Jarno.Elovirta@xxxxxxxxx] Sent: Wednesday, August 21, 2002 11:30 PM To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Subject: RE: [xsl] sorting a subset of elements Hi, > I have created an xml document with over 300 items sorted by > price. For the > internet I want to display all items, however for print I only want to > display the 90 most expensive and i want them sorted > alpabetically. I am > not sure how to accomplish this. You can't sort, filter and sort again with XSLT 1.0; using XSLT 1.1 or 2.0 you could sort the items into a variable and sort it again. So, either do two transformations, where you sort by price and filter in the first one, and sort by name in the second one; or write a recursive template that will select the first 50 most expensive items, but that will probably be quite inefficient, e.g. (should work) <?xml version='1.0' encoding='UTF-8' ?> <xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <xsl:template match="itemlist"> <xsl:copy> <xsl:call-template name="max-n"> <xsl:with-param name="ns" select="item" /> </xsl:call-template> </xsl:copy> </xsl:template> <xsl:template match="item"> <xsl:copy-of select="." /> </xsl:template> <xsl:template name="max-n"> <xsl:param name="ns" select="/.." /> <xsl:param name="selected" select="/.." /> <xsl:param name="n" select="50"/> <xsl:choose> <xsl:when test="not(count($ns) = 0) and count($selected) < $n"> <xsl:variable name="max"> <xsl:call-template name="max"> <xsl:with-param name="ns" select="$ns" /> </xsl:call-template> </xsl:variable> <xsl:variable name="tbs" select="$ns[@price = $max]" /> <xsl:call-template name="max-n"> <xsl:with-param name="ns" select="$ns[not(@price = $max)]" /> <xsl:with-param name="selected" select="$selected | $ns[@price = $max][position() < ($n + 1 - count($selected))]" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="$selected"> <xsl:sort select="@description" /> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="max"> <xsl:param name="ns" select="/.." /> <xsl:choose> <xsl:when test="count($ns) > 2"> <xsl:variable name="c" select="ceiling(count($ns) div 2)" /> <xsl:variable name="head"> <xsl:call-template name="max"> <xsl:with-param name="ns" select="$ns[position() <= $c]" /> </xsl:call-template> </xsl:variable> <xsl:variable name="tail"> <xsl:call-template name="max"> <xsl:with-param name="ns" select="$ns[position() > $c]" /> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$head > $tail"> <xsl:value-of select="$head" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$tail" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="count($ns) > 1"> <xsl:choose> <xsl:when test="$ns[1]/@price > $ns[2]/@price"> <xsl:value-of select="$ns[1]/@price" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$ns[2]/@price" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select="$ns/@price" /> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> But you do not want that with 300 items, especially if just about every item has a unique price; so go with the two (chained) transformations. Cheers, Jarno XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] sorting a subset of eleme, Jarno . Elovirta | Thread | RE: [xsl] sorting a subset of eleme, James Fuller |
RE: [xsl] telling processor what to, abradoom | Date | RE: [xsl] sorting a subset of eleme, James Fuller |
Month |