0

Is it possible in XSLT-1.0 to sort by a value in the xml. In the example below the <examples> has requested that that the list of <example>s be sorted by the year field.

...
<examples>
  <sortby>year</sortby>

  <example>
    <year>2012</year>
    <number>3</number>
  </example>

</examples>
...

A static conditional using choose does not work in this case as I will not know what the possible fields in <example> will be.

1
  • It's possible using xsl:sort Commented Aug 7, 2012 at 12:02

3 Answers 3

1

Yes, use something of this form:

<xsl:apply-templates select="example">
  <xsl:sort select="*[name()=sortby]" data-type="{sort-data-type}" 
            order="{sort-order}" />
</xsl:apply-templates>

Do note that you need to also specify the sort data-type and order.

Complete example:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:copy>
    <xsl:apply-templates select="example">
      <xsl:sort select="*[name()=/*/sortby]" data-type="{/*/sort-data-type}"
                order="{/*/sort-order}" />
    </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="example">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document:

<examples>
    <sortby>year</sortby>
    <sort-data-type>number</sort-data-type>
    <sort-order>descending</sort-order>
    <example>
        <year>2008</year>
        <number>3</number>
    </example>
    <example>
        <year>2012</year>
        <number>2</number>
    </example>
    <example>
        <year>2010</year>
        <number>5</number>
    </example>
</examples>

the wanted, correct result is produced:

<examples>
   <example>
      <year>2012</year>
      <number>2</number>
   </example>
   <example>
      <year>2010</year>
      <number>5</number>
   </example>
   <example>
      <year>2008</year>
      <number>3</number>
   </example>
</examples>

If the same transformation is applied on this XML document (the same as above, but with changed sortby and sort-order):

<examples>
    <sortby>number</sortby>
    <sort-data-type>number</sort-data-type>
    <sort-order>ascending</sort-order>
    <example>
        <year>2008</year>
        <number>3</number>
    </example>
    <example>
        <year>2012</year>
        <number>2</number>
    </example>
    <example>
        <year>2010</year>
        <number>5</number>
    </example>
</examples>

then again the wanted, correct result is produced:

<examples>
   <example>
      <year>2012</year>
      <number>2</number>
   </example>
   <example>
      <year>2008</year>
      <number>3</number>
   </example>
   <example>
      <year>2010</year>
      <number>5</number>
   </example>
</examples>

Explanation:

  1. The select attribute of xsl:sort can contain any XPath expression, so we can specify an expression that selects any child of the elements to be sorted, such that its name is the result of evaluating another XPath expression.

  2. In XSLT, typically, all attributes other than select allow *AVT*s (Attribute Value Templates) to be specified in their values.

Sign up to request clarification or add additional context in comments.

Comments

0

Sort by *[local-name() = $your-sort-item], e.g.

<xsl:template match="examples">
  <xsl:variable name="sort-name" select="sortby"/>
  <xsl:apply-templates select="example">
    <xsl:sort select="*[local-name() = $sort-name]"/>
  </xsl:apply-templates>
</xsl:template>

Comments

0

I assume you mean the node on which you sort should be dynamic, read from the examples/sortBy node. This being the case:

<xsl:template match="examples">
    <xsl:apply-templates select='example'>
        <xsl:sort
            select='*[name() = /examples/sortby]'
            data-type='number'
            order='descending' 
        />
    </xsl:apply-templates>
</xsl:template>
<xsl:template match='example'>
    <p><xsl:value-of select='year' /></p>
</xsl:template>

Runnable demo at this XML Playground.

That outputs each year, each as a paragraph. Change 'descending' to 'ascending' as required.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.