A while back, a couple of people were asking how to display a field in XSLT in a recursive manner. I recently had to call a field in a recursive manner, with a bit of logic, and thought I would share my knowledge.
Simple RecursionTo select a single field in a recursive manner is actually quite simple.
Code:
<xsl:value-of select="$currentPage/ancestor-or-self::node [string(data[@alias='field'])!=''] [position()=last()] /data[@alias='field']"/>
The trick behind this is that for each node returned with a value on the field requested, that the last one (closest parent node), is the one we want to retrieve. Thus, the last position.
Of course, if you are rotating through a set of nodes with a for-each call, you can replace the $currentPage with . or current().
Conditional RecursionIf you have a more logic based situation (simple conditions), such that one field dictates the display of the other, you can add your logic into the xslt select, expanding the Simple Recursion with additional clauses.
For instance, I have two fields that determine the display of an object on a page. One field, 'hideField', is a yes/no data type, and the other, 'Field', is a textbox multiple.
I want to display my 'Field' recursively, but only if the 'hideField' has not been set to yes (1) along the way. For that, I have to extend the selection a bit. This could also be accomplished with an if statement, but I think this manner is a bit cleaner for this example.
Code:
<xsl:value-of select="$currentPage/ancestor-or-self::node [string(data[@alias='Field'])!='' or data[@alias='hideField']=1] [position()=last()] [data[@alias='hideField']!=1] /data[@alias='Field']"/>
What this is basically doing is finding the last node (closest parent) that either has content in the Field or the hideField option is set to yes(1). If that last item does not have hideField set to yes(1)[aka, it is set to no], then the Field is displayed.
Fallback RecursionIf you want to display a secondary field if the primary is not available, but maintain the recursive approach, some fun coding must occur. It isn't as pretty, but, it gets the job done.
Code:
<xsl:value-of select="$currentPage/ancestor-or-self::node [string(data[@alias='Primary'])!='' or string(data[@alias='Secondary'])!=''] [position()=last()] [data[@alias='Primary']!=''] /data[@alias='Primary']"/>
<xsl:value-of select="$currentPage/ancestor-or-self::node [string(data[@alias='Primary'])!='' or string(data[@alias='Secondary'])!=''] [position()=last()] [data[@alias='Secondary']!='' and data[@alias='Primary']=''] /data[@alias='Secondary']"/>
What this xslt statement is doing is Looking at the Primary and Secondary fields on the node tree. If either one has a value, the node is selected, from which we take the last node (closest parent). We then test for data in the Primary field, which if it contains data, we are shown that field. The second statement does the same as the first, however, it tests for data on the Secondary field, but only if there is no data on the Primary field, as we don't want to show both fields.
Additional ThoughtsIf you are trying to read content from a field that uses the Richtext Editor, you may have to apply the umbraco.library:StripHtml function into your code, as to keep you from selecting a field that has a set of paragraph tags, but no content.
While these solutions may not be an exact answer to your needs, I hope it opens up the possibilities that XSLT can do for you.
As a side note, I did not test every example here (specifically the last example), but did test the first and second examples, barring any typing errors.
Case
• 2007/2008 MVP • 2008/2009 MVP • Certified •
Best Case Technologies, LLC• Umbraco Licensing • Support Packages • Web and Application Development • Hosting • Multi-Lingual Site •