Search code examples
xmlxsltxpath

Using Variables in <xsl:sort select=""/>


Hi am build a generic template to list my content. But the Content may be sorted on different @'s or node()'s. So want to pass the xPath in.

<xsl:variable name="sort" select="@sortBy"/>
<xsl:variable name="order" select="@order"/>

<xsl:for-each select="Content[@type=$contentType]">
  <xsl:sort select="$sort" order="{$order}" data-type="text"/>
  <xsl:sort select="@update" order="{$order}" data-type="text"/>
    <xsl:copy-of select="."/>
</xsl:for-each>

Using a variable to drop in ascending or descending into the order="" WORKS.

Why cannot do this on the select="" ?

I hoping to make this super dynamic the select variable can be xPtah either @publish or Title/node() or any xPath.

There is no error - It just ignores the sort.


Solution

  • This is by design. The select attribute is the only one which doesnt accept AVTs (Attribute - Value Templates).

    The usual solution is to define a variable with the name of the child element that should be used as sort key. Below is a small example:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:variable name="vsortKey" select="'b'"/>
     <xsl:variable name="vsortOrder" select="'descending'"/>
    
     <xsl:template match="/*">
       <xsl:for-each select="*">
        <xsl:sort select="*[name() = $vsortKey]" order="{$vsortOrder}"/>
    
        <xsl:copy-of select="."/>
       </xsl:for-each>
     </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is applied on the following XML document:

    <t>
      <a>
       <b>2</b>
       <c>4</c>
      </a>
      <a>
       <b>5</b>
       <c>6</c>
      </a>
      <a>
       <b>1</b>
       <c>7</c>
      </a>
    </t>
    

    the wanted result is produced:

    <a>
       <b>5</b>
       <c>6</c>
      </a>
    <a>
       <b>2</b>
       <c>4</c>
      </a>
    <a>
       <b>1</b>
       <c>7</c>
    </a>