Max
Max

Reputation: 1563

XSLT Apply sort to second value if first is empty

I have a for each which loops round news item nodes. Among other properties these news items have two attributes for created date. System added date and a user entered created date (to override the system date). I would like the list sorted by created date with the preference on the user entered date.

Below is my humble invalid attempt!

<xsl:for-each select="$currentPage/ancestor-or-self::node /node [@nodeTypeAlias = $documentTypeAlias and string(data [@alias='umbracoNaviHide']) != '1']">

<xsl:choose>
 <xsl:when test="data [@alias = 'createdDate'] != ''">
  <xsl:variable name="sort" select="string(data [@alias = 'createdDate'])"/>
 </xsl:when>
 <xsl:otherwise>
  <xsl:variable name="sort" select="string(@createDate)"/>
 </xsl:otherwise>
</xsl:choose>

<xsl:sort select="$sort" order="descending"/>

Many thanks

Upvotes: 0

Views: 2597

Answers (4)

Red Taz
Red Taz

Reputation: 4179

Many thanks to Erlock for his solution. I did struggle for a while to get this working in my version of Umbraco (4.7.1) due to the changes made to the Umbraco XSLT syntax.

For anyone interested, my working sample would change Erlock's code to become;

<xsl:sort select="(current()/createdDate[normalize-space() != '']|@createDate)[last()]" order="descending" />

Upvotes: 0

Erlock
Erlock

Reputation: 1968

<xsl:sort select="(data[@alias='createdDate' and normalize-space() != '']|@createDate)[last()]" order="descending" />

This statement creates a nodeset with the two nodes containing date, and get the last one according the document order to do the sorting. If data node exists and is not empty, it will be used for the sorting because child elements of an element occur after its attribute nodes.

concat() can only work, and in a few cases, if you use text sorting; it will fail with numeric sorting.

Upvotes: 7

BalusC
BalusC

Reputation: 1109112

To test if a node is empty (or omitted) in XSLT:

<xsl:when test="not(string(name))">...</xsl:when>
<!-- or -->
<xsl:when test="not(name)">...</xsl:when>

Upvotes: 0

Max
Max

Reputation: 1563

Right, seems like a hack but I have been able to achieve this by using a concat with the sort.

Example below

<xsl:for-each select="$currentPage/ancestor-or-self::node /node [@nodeTypeAlias = $documentTypeAlias and string(data [@alias='umbracoNaviHide']) != '1']">
<xsl:sort select="concat(data [@alias = 'createdDate'],@createDate)" order="descending"/>

Upvotes: 0

Related Questions