Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Sorting in XSLT
by Bob DuCharme | Pages: 1, 2, 3, 4

Let's look at how the xsl:for-each instruction can use xsl:sort. The following stylesheet takes the same winelist document above and lists the wines. When it gets to a Chardonnay, it lists all the other Chardonnays alphabetically.

<!-- xq439.xsl: converts xq436.xml into xq440.txt -->
<!DOCTYPE stylesheet [
<!ENTITY space "<xsl:text> </xsl:text>">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>

  <xsl:template match="wine">
   <xsl:apply-templates select="winery"/>&space;
   <xsl:apply-templates select="product"/>&space;
   <xsl:apply-templates select="year"/>&space;
   <xsl:apply-templates select="@grape"/>
   <xsl:if test="@grape = 'Chardonnay'">
    <xsl:text>
  other Chardonnays:
</xsl:text>
    <xsl:for-each 
      select="preceding-sibling::wine[@grape = 'Chardonnay'] |
                     following-sibling::wine[@grape = 'Chardonnay']">
      <xsl:sort select="winery"/>
      <xsl:text>    </xsl:text>
      <xsl:value-of select="winery"/>&space;
      <xsl:value-of select="product"/><xsl:text>
</xsl:text>
    </xsl:for-each>
    </xsl:if>
</xsl:template>

Before we examine how the stylesheet does this, let's take a look at the result:

  Lindeman's Bin 65 1998 Chardonnay
  other Chardonnays:
    Benziger Carneros
    Kendall Jackson Vintner's Reserve

Benziger Carneros 1997 Chardonnay
  other Chardonnays:
    Kendall Jackson Vintner's Reserve
    Lindeman's Bin 65

  Duckpond Merit Selection 1996 Cabernet

  Kendall Jackson Vintner's Reserve 1998 Chardonnay
  other Chardonnays:
    Benziger Carneros
    Lindeman's Bin 65

(First, notice the "&space;" entity references throughout the stylesheet. Instead of writing "<xsl:text> </xsl:text>" over and over because I needed single spaces in so many places, it was easier to declare an entity named space in the DOCTYPE declaration with this xsl:text element as content and to then plug it in with an entity reference whenever I needed it.) The xsl:template template rule for the wine element has xsl:apply-templates instructions for its winery, product, and year element children followed by one for its grape attribute. Then, if the grape attribute has a value of "Chardonnay", it adds the text "other Chardonnays:" to the result tree followed by the list of Chardonnays, which are added to the result tree using an xsl:for-each instruction.

The select attribute of the xsl:for-each attribute selects all the nodes that are either preceding siblings of the current node with a grape value of "Chardonnay" or following siblings of the current node with the same grape value. (The "|" symbol is the "or" part.) For each wine element that meets this select attribute's condition, the template first adds some white space indenting with an xsl:text element, then the value of the wine element's winery child, a space, and the value of its product child. The first instruction in this xsl:for-each element is an xsl:sort element, which tells the XSLT processor to sort the nodes selected by the xsl:for-each instruction alphabetically in "winery" order. That's how they look in the result: after the first "other Chardonnays:" label, "Kendall Jackson" comes after "Benziger"; after the second, "Lindeman's" comes after "Kendall Jackson"; and after the last one, "Lindeman's" comes after "Benziger".

Because the xsl:for-each instruction lets you grab and work with any node set that you can describe using an XPath expression, the ability to sort one of these node sets makes it one of XSLT's most powerful features.

Next month, we'll see how xsl:sort can help find the first, last, biggest, and smallest value in a document according to a certain criteria. (If you can't wait, see my book XSLT Quickly, from which these columns are excerpted.)


Comment on this articleHave you found interesting uses for xsl:sort? Share your discoveries in our forum.
(* You must be a
member of XML.com to use this feature.)
Comment on this Article


Titles Only Titles Only Newest First
  • great article thanks
    2009-05-09 09:14:10 jixel [Reply]

    i wasn't sure if/how to do a cascading sort and truthfully this article is the best one out there on the subject

  • xsl:sort
    2007-07-13 06:16:06 ArsenyX [Reply]

    In my XML text is in CDATA.
    What do I need to sort text on alphabet?
    Thanks in advance.

  • sort
    2005-11-28 12:51:49 harvy [Reply]

    Is it possible to sort by order of nodes as they are in the xml list?
    ie if teh xml file is:
    a
    b
    c


    and i want to reverse the order so that it displays


    c
    b
    a


    what do i sort with?


    • sort
      2006-04-20 05:58:37 jbautista [Reply]

      Were you able to figure this out? I'm trying to do something similar. I want to sort by the node names, a,b,c:
      <element>
      <a/>
      </element>
      <element>
      <b/>
      </element>
      <element>
      <c/>
      </element>


      Thanks in advance!

  • Custom built xsl:sort
    2005-09-06 18:49:53 srinivasvemuri [Reply]

    Hi,


    How do i proceed if i were to sort say using Time Period, where my values are Early Bronze, A.D.,BYZANTINE, IRON I. i.e., Sorting with domain knowledge!!!

    • Custom built xsl:sort
      2005-09-06 19:23:45 Bob DuCharme [Reply]

      XSLT sorts alphabetically or numerically. It would be an interesting exercise to map your values to alphanumeric key values and trying to sort by those, though.

      • Custom built xsl:sort
        2005-09-07 12:22:45 srinivasvemuri [Reply]

        Thanks for the suggestion. Could you explain in detail. I have a different xml file that maps each time period to an integer.
        ex. period.xml --->
        <entry period="middlebronze">1</entry>
        <entry period="byzantine">2</entry>
        <entry period="Roman">3</entry>
        <entry period="islamic">4</entry>


        How do above file in xslt sort based on time period? I am trying something like this!!!!
        <xsl:for-each select="timeperiod">
        <xsl:sort select='key(?,?)' />
        </xsl:for-each>


        • Custom built xsl:sort
          2005-09-07 14:02:01 Bob DuCharme [Reply]

          I haven't followed through on this myself, and doing so and then providing a detailed explanation will take more time than I have available right now. I suggest you try the XSL-list at http://www.mulberrytech.com/xsl/xsl-list/.

  • Xml and XSLT
    2004-04-27 00:52:07 bertcox [Reply]

    hello,


    I'm using C# to display Xml-data in a datagrid. Now i want the datagrid to be sorted. I heard the best way to sort the xml-file is to use XSLT. I'm new to c#,xml and xslt so i don't really know what to do. I read your article and it's defenitely the best i've found. But there are some things i do not understand. I can call the XSLT-file in C#? Does it create a new Xml-file? Or just sorts the original and saves it?


    Thx a lot in advance,


    Bert Cox


    • Xml and XSLT
      2004-05-29 06:56:13 Kitsuneymg [Reply]

      to associate an xml file with an xsl file include this line in the xml file right after the <?xml version=......?>


      <<?xml-stylesheet alternate="no" href="myxsl.xsl" type="text/xsl"?>

  • static or dynamic...?
    2004-01-10 13:10:05 john clariond [Reply]

    XSLT is well explain, OK.
    I understand that the result is static, informations are seen like the XSLT stylesheet is write, because we must call the XML file...OK ?
    and in this XML file is the hard reference to the XSLT stylesheet...!
    But... how can we insert a choice in the web pages...?


    Thank'a a lot.

  • Parameters
    2002-09-04 03:53:25 Dave Goodman [Reply]

    Great article, but one omission - How do you pass through the direction or attribute to sort on dynamically - e.g. as a parameter to the url, e.g.
    http://www.mysite.com/sorted.xml?direction=Ascending


    Regards


    Dave

    • Parameters
      2004-05-29 07:00:03 Kitsuneymg [Reply]

      try looking for javascript, php, asp, or jsp solutions

  • xsl:sort
    2002-08-02 00:49:54 aneesh kumar [Reply]

    a good article - congrats!!!

    • xsl:sort
      2002-08-13 06:03:14 charles asafo [Reply]

      How do I eliminate duplicates after sorting?
      The following :
      boy
      boy
      girl
      man
      man
      woman
      should become
      boy
      girl
      man
      woman

  • xsl:sort
    2002-07-04 09:07:34 Vijayalaxmi Balcha [Reply]

    Very good explanation with illustrations.

  • Use of xsl:sort
    2002-07-04 05:38:50 Raj Krishnan [Reply]

    This is a very good article. A simple concept explained well. THe arrangement of the subject in a porgressively advanced format makes it interesting and allows the reader to use the sort function in several ways.


    Good work!